From fc28cc102ad3c81f7e44311832d0b194326bab4b Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sat, 18 Apr 2026 22:37:03 +0200 Subject: [PATCH 01/11] Rename fixtures and pytest options --- narwhals/testing/constructors.py | 70 ++++++++++----------- narwhals/testing/pytest_plugin.py | 100 ++++++++++++++---------------- 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/narwhals/testing/constructors.py b/narwhals/testing/constructors.py index cf838d3098..7e4d724b3a 100644 --- a/narwhals/testing/constructors.py +++ b/narwhals/testing/constructors.py @@ -1,11 +1,11 @@ """Concrete constructor classes and auto-registration machinery. -Each constructor wraps one backend library (pandas, Polars, DuckDB, ...) -and knows how to turn a column-oriented `dict` into a native frame. +Each constructor wraps one backend library (pandas, Polars, DuckDB, ...) and +knows how to turn a column-oriented `dict` into a native frame. -All static metadata for a backend lives on its constructor class, colocated -with the `__call__` implementation. Adding a constructor is a one-step -declaration — the `__init_subclass__` hook then auto-registers a singleton. +All static metadata for a backend lives on its constructor class, colocated with +the `__call__` implementation. Adding a constructor is a one-step declaration. +The `__init_subclass__` hook then auto-registers a singleton. ## Adding a new constructor @@ -65,15 +65,15 @@ def __call__(self, obj: Data, /, **kwds: Any) -> ...: __all__ = ( - "ALL_CONSTRUCTORS", - "ALL_CPU_CONSTRUCTORS", - "DEFAULT_CONSTRUCTORS", + "ALL_BACKENDS", + "ALL_CPU_BACKENDS", + "DEFAULT_BACKENDS", "EagerFrameConstructor", "FrameConstructor", - "available_constructors", - "get_constructor", + "available_backends", + "get_backend_constructor", "is_backend_available", - "prepare_constructors", + "prepare_backends", "pyspark_session", "sqlframe_session", ) @@ -529,10 +529,10 @@ def __call__(self, obj: Data, /, **kwds: Any) -> ibis.Table: return _ibis_backend().create_table(table_name, table, **kwds) -ALL_CONSTRUCTORS: dict[str, FrameConstructor] = FrameConstructor._registry -"""All registered constructors keyed by their string identifier.""" +ALL_BACKENDS: dict[str, FrameConstructor] = FrameConstructor._registry +"""All registered backends keyed by their string identifier.""" -DEFAULT_CONSTRUCTORS: frozenset[str] = frozenset( +DEFAULT_BACKENDS: frozenset[str] = frozenset( { "pandas", "pandas[pyarrow]", @@ -543,28 +543,28 @@ def __call__(self, obj: Data, /, **kwds: Any) -> ibis.Table: "ibis", } ) -"""Subset of constructors enabled by default for parametrised tests when the -user does not pass `--constructors` (mirrors the historical Narwhals defaults). +"""Subset of backends enabled by default for parametrised tests when the +user does not pass `--nw-backends` (mirrors the historical Narwhals defaults). """ -ALL_CPU_CONSTRUCTORS: frozenset[str] = frozenset( +ALL_CPU_BACKENDS: frozenset[str] = frozenset( name for name, c in FrameConstructor._registry.items() if not c.needs_gpu ) -"""All constructors that do not require GPU hardware.""" +"""All backends that do not require GPU hardware.""" -def available_constructors() -> frozenset[str]: +def available_backends() -> frozenset[str]: """Return the names of every constructor whose backend is importable. Examples: - >>> from narwhals.testing.constructors import available_constructors - >>> "pandas" in available_constructors() + >>> from narwhals.testing.constructors import available_backends + >>> "pandas" in available_backends() True """ - return frozenset(name for name, c in ALL_CONSTRUCTORS.items() if c.is_available) + return frozenset(name for name, c in ALL_BACKENDS.items() if c.is_available) -def get_constructor(name: str) -> FrameConstructor: +def get_backend_constructor(name: str) -> FrameConstructor: """Return the registered singleton constructor for `name`. Arguments: @@ -575,34 +575,34 @@ def get_constructor(name: str) -> FrameConstructor: ValueError: If `name` is not a registered constructor identifier. Examples: - >>> from narwhals.testing.constructors import get_constructor - >>> get_constructor("pandas") + >>> from narwhals.testing.constructors import get_backend_constructor + >>> get_backend_constructor("pandas") PandasConstructor() """ try: - return ALL_CONSTRUCTORS[name] + return ALL_BACKENDS[name] except KeyError as exc: - valid = sorted(ALL_CONSTRUCTORS) + valid = sorted(ALL_BACKENDS) msg = f"Unknown constructor {name!r}. Expected one of: {valid}." raise ValueError(msg) from exc -def prepare_constructors( +def prepare_backends( *, include: Iterable[str] | None = None, exclude: Iterable[str] | None = None ) -> list[FrameConstructor]: - """Return available constructors, optionally filtered. + """Return available backends, optionally filtered. Arguments: - include: If given, only return constructors whose name is in this set. - exclude: If given, remove constructors whose name is in this set. + include: If given, only return backends whose name is in this set. + exclude: If given, remove backends whose name is in this set. Examples: - >>> from narwhals.testing.constructors import prepare_constructors - >>> constructors = prepare_constructors(include=["pandas", "polars[eager]"]) + >>> from narwhals.testing.constructors import prepare_backends + >>> backends = prepare_backends(include=["pandas", "polars[eager]"]) """ - available = available_constructors() + available = available_backends() candidates: list[FrameConstructor] = [ - c for name, c in ALL_CONSTRUCTORS.items() if name in available + c for name, c in ALL_BACKENDS.items() if name in available ] if include is not None: inc = frozenset(include) diff --git a/narwhals/testing/pytest_plugin.py b/narwhals/testing/pytest_plugin.py index 9d08fa380e..34c9221207 100644 --- a/narwhals/testing/pytest_plugin.py +++ b/narwhals/testing/pytest_plugin.py @@ -1,13 +1,11 @@ -"""Narwhals pytest plugin - auto-parametrises `constructor*` fixtures. +"""Narwhals pytest plugin - auto-parametrises fixtures. -NOTE: All imports from `narwhals.*` are deferred inside the hook functions so -that the entry-point module can be loaded by pytest without pulling in the -narwhals package tree. +NOTE: All imports from `narwhals.*` are deferred inside the hook functions so that +the entry-point module can be loaded by pytest without pulling in the narwhals package tree. -This is critical because entry-point plugins are loaded *before* `pytest-cov` -starts coverage measurement; any narwhals module imported at that stage would -have its module-level code (class definitions, constants, etc.) executed outside -the coverage tracer. +This is critical because entry-point plugins are loaded *before* `coveragepy` starts +coverage measurement; any narwhals module imported at that stage would have its +module-level code (class definitions, constants, etc.) executed outside the coverage tracer. """ from __future__ import annotations @@ -36,72 +34,64 @@ def _pandas_version() -> tuple[int, ...]: return parse_version(pd.__version__) -def _default_constructor_ids() -> list[str]: - """Resolve the default `--constructors` value for the current environment. +def _default_backend_ids() -> list[str]: + """Resolve the default `--nw-backends` value for the current environment. - Honours `NARWHALS_DEFAULT_CONSTRUCTORS` if set, otherwise restricts - [`DEFAULT_CONSTRUCTORS`][] to backends whose libraries are importable. + Honours `NARWHALS_DEFAULT_BACKENDS` if set, otherwise restricts + [`DEFAULT_BACKENDS`][] to backends whose libraries are importable. """ - if env := os.environ.get("NARWHALS_DEFAULT_CONSTRUCTORS"): # pragma: no cover + if env := os.environ.get("NARWHALS_DEFAULT_BACKENDS"): # pragma: no cover return env.split(",") - from narwhals.testing.constructors import DEFAULT_CONSTRUCTORS, prepare_constructors + from narwhals.testing.constructors import DEFAULT_BACKENDS, prepare_backends - return [c.name for c in prepare_constructors(include=DEFAULT_CONSTRUCTORS)] + return [c.name for c in prepare_backends(include=DEFAULT_BACKENDS)] def pytest_addoption(parser: pytest.Parser) -> None: - from narwhals.testing.constructors import DEFAULT_CONSTRUCTORS + from narwhals.testing.constructors import DEFAULT_BACKENDS - group = parser.getgroup("narwhals", "narwhals.testing") - defaults = ", ".join(f"'{c}'" for c in sorted(DEFAULT_CONSTRUCTORS)) + group = parser.getgroup("narwhals", "narwhals-testing") + defaults = ", ".join(f"'{c}'" for c in sorted(DEFAULT_BACKENDS)) group.addoption( - "--constructors", + "--nw-backends", action="store", - default=",".join(_default_constructor_ids()), + default=",".join(_default_backend_ids()), type=str, help=( - "Comma-separated list of backend constructors to parametrise. " - f"Defaults to the installed subset of ({defaults})" + "Comma-separated list of (data|lazy) frame backend constructors to" + f"parametrise. Defaults to the installed subset of ({defaults})" ), ) group.addoption( - "--all-cpu-constructors", + "--all-nw-backends", action="store_true", default=False, - help=( - "Run tests against every installed CPU constructor " - "(overrides --constructors)." - ), + help=("Run tests against every installed CPU backend (overrides --nw-backends)."), ) - # Escape hatch for downstream test suites that ship their own constructor - # plugin. When set, this plugin still adds the CLI options but stops - # parametrising the fixtures. + # Escape hatch for downstream test suites that ship their own backend plugin. + # When set, this plugin still adds the CLI options but stops parametrising the fixtures. group.addoption( - "--use-external-constructor", + "--use-external-backend", action="store_true", default=False, help=( - "Skip narwhals.testing's parametrisation and let another plugin " - "provide the `constructor*` fixtures." + "Skip narwhals-testing's parametrisation and let another plugin " + "provide the `nw_*frame_constructor` fixtures." ), ) -def _select_constructors( - config: pytest.Config, -) -> list[FrameConstructor]: # pragma: no cover - from narwhals.testing.constructors import ALL_CPU_CONSTRUCTORS, prepare_constructors +def _select_backends(config: pytest.Config) -> list[FrameConstructor]: # pragma: no cover + from narwhals.testing.constructors import ALL_CPU_BACKENDS, prepare_backends _all_cpu_exclusions = frozenset({"modin", "pyspark[connect]"}) - if config.getoption("all_cpu_constructors"): - selected = prepare_constructors( - include=ALL_CPU_CONSTRUCTORS, exclude=_all_cpu_exclusions - ) + if config.getoption("all_nw_backends"): + selected = prepare_backends(include=ALL_CPU_BACKENDS, exclude=_all_cpu_exclusions) else: - opt = cast("str", config.getoption("constructors")) + opt = cast("str", config.getoption("nw_backends")) names = [c for c in opt.split(",") if c] - selected = prepare_constructors(include=names) + selected = prepare_backends(include=names) if _pandas_version() < _MIN_PANDAS_NULLABLE_VERSION: _pandas_nullables = {"pandas[nullable]", "pandas[pyarrow]"} @@ -110,24 +100,30 @@ def _select_constructors( def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: - if metafunc.config.getoption("use_external_constructor"): # pragma: no cover + if metafunc.config.getoption("use_external_backend"): # pragma: no cover return fixturenames = set(metafunc.fixturenames) - if not fixturenames & {"constructor", "constructor_eager", "constructor_pandas_like"}: + if not fixturenames & { + "nw_frame_constructor", + "nw_eager_frame_constructor", + "nw_pandas_like_constructor", + }: return - selected = _select_constructors(metafunc.config) + selected = _select_backends(metafunc.config) - if "constructor_eager" in fixturenames: + if "nw_eager_frame_constructor" in fixturenames: params = [c for c in selected if c.is_eager] ids = [c.name for c in params] - metafunc.parametrize("constructor_eager", params, ids=ids) - elif "constructor" in fixturenames: - metafunc.parametrize("constructor", selected, ids=[c.name for c in selected]) - elif "constructor_pandas_like" in fixturenames: + metafunc.parametrize("nw_eager_frame_constructor", params, ids=ids) + elif "nw_frame_constructor" in fixturenames: + metafunc.parametrize( + "nw_frame_constructor", selected, ids=[c.name for c in selected] + ) + elif "nw_pandas_like_constructor" in fixturenames: params = [c for c in selected if c.is_eager and c.is_pandas_like] ids = [c.name for c in params] - metafunc.parametrize("constructor_pandas_like", params, ids=ids) + metafunc.parametrize("nw_pandas_like_constructor", params, ids=ids) else: # pragma: no cover ... From 244123ca033c457d6ee2163b1351edaa9fea968e Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sat, 18 Apr 2026 22:37:28 +0200 Subject: [PATCH 02/11] fix imports --- tests/hypothesis/getitem_test.py | 5 ++-- tests/ibis_test.py | 4 +-- tests/series_only/hist_test.py | 4 +-- tests/testing/constructors_test.py | 44 ++++++++++++++++------------- tests/translate/from_native_test.py | 6 ++-- 5 files changed, 35 insertions(+), 28 deletions(-) diff --git a/tests/hypothesis/getitem_test.py b/tests/hypothesis/getitem_test.py index 60419f48a2..54d404b4e2 100644 --- a/tests/hypothesis/getitem_test.py +++ b/tests/hypothesis/getitem_test.py @@ -7,7 +7,7 @@ from hypothesis import assume, given import narwhals as nw -from narwhals.testing.constructors import get_constructor +from narwhals.testing.constructors import get_backend_constructor from tests.utils import assert_equal_data if TYPE_CHECKING: @@ -21,7 +21,8 @@ @pytest.fixture( - params=[get_constructor("pandas"), get_constructor("pyarrow")], scope="module" + params=[get_backend_constructor("pandas"), get_backend_constructor("pyarrow")], + scope="module", ) def pandas_or_pyarrow_constructor( request: pytest.FixtureRequest, diff --git a/tests/ibis_test.py b/tests/ibis_test.py index f537ef1c99..10dce38413 100644 --- a/tests/ibis_test.py +++ b/tests/ibis_test.py @@ -3,11 +3,11 @@ import pytest import narwhals as nw -from narwhals.testing.constructors import get_constructor +from narwhals.testing.constructors import get_backend_constructor def test_from_native() -> None: - ibis_constructor = get_constructor("ibis") + ibis_constructor = get_backend_constructor("ibis") if not ibis_constructor.is_available: pytest.skip() df = nw.from_native(ibis_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) diff --git a/tests/series_only/hist_test.py b/tests/series_only/hist_test.py index 18468cc783..882c658f27 100644 --- a/tests/series_only/hist_test.py +++ b/tests/series_only/hist_test.py @@ -11,7 +11,7 @@ import narwhals as nw from narwhals.exceptions import ComputeError -from narwhals.testing.constructors import get_constructor +from narwhals.testing.constructors import get_backend_constructor from tests.utils import POLARS_VERSION, ConstructorEager, assert_equal_data if TYPE_CHECKING: @@ -48,7 +48,7 @@ def maybe_name_to_constructor(name: str) -> ConstructorEager: - constructor = get_constructor(name) + constructor = get_backend_constructor(name) if constructor.is_available: return constructor # type: ignore[return-value] diff --git a/tests/testing/constructors_test.py b/tests/testing/constructors_test.py index 422dbd8372..5e37534a7d 100644 --- a/tests/testing/constructors_test.py +++ b/tests/testing/constructors_test.py @@ -8,8 +8,8 @@ from narwhals._utils import Implementation from narwhals.testing.constructors import ( FrameConstructor, - get_constructor, - prepare_constructors, + get_backend_constructor, + prepare_backends, ) if TYPE_CHECKING: @@ -21,7 +21,7 @@ def test_eager_returns_eager_frame() -> None: - c = get_constructor("pandas") + c = get_backend_constructor("pandas") if not c.is_available: pytest.skip() @@ -30,7 +30,7 @@ def test_eager_returns_eager_frame() -> None: def test_lazy_returns_lazy_frame() -> None: - c = get_constructor("polars[lazy]") + c = get_backend_constructor("polars[lazy]") if not c.is_available: pytest.skip() @@ -62,30 +62,34 @@ def test_constructor_is_properties( prop: str, true_names: TrueNames, false_names: FalseNames ) -> None: for name in true_names: - c = get_constructor(name) + c = get_backend_constructor(name) assert getattr(c, prop), f"{name}.{prop} should be True" for name in false_names: - c = get_constructor(name) + c = get_backend_constructor(name) assert not getattr(c, prop), f"{name}.{prop} should be False" def test_constructor_implementation() -> None: - assert get_constructor("pandas").implementation is Implementation.PANDAS - assert get_constructor("pandas[pyarrow]").implementation is Implementation.PANDAS - assert get_constructor("polars[eager]").implementation is Implementation.POLARS + assert get_backend_constructor("pandas").implementation is Implementation.PANDAS assert ( - get_constructor("pyspark[connect]").implementation + get_backend_constructor("pandas[pyarrow]").implementation is Implementation.PANDAS + ) + assert ( + get_backend_constructor("polars[eager]").implementation is Implementation.POLARS + ) + assert ( + get_backend_constructor("pyspark[connect]").implementation is Implementation.PYSPARK_CONNECT ) def test_constructor_dunder() -> None: - c1 = get_constructor("pandas") - c2 = get_constructor("pandas") + c1 = get_backend_constructor("pandas") + c2 = get_backend_constructor("pandas") assert c1.identifier == "pandas" assert c1 == c2 assert hash(c1) == hash(c2) - assert c1 != get_constructor("polars[eager]") + assert c1 != get_backend_constructor("polars[eager]") assert c1 != "not a constructor" @@ -99,16 +103,18 @@ def __call__(self, obj: object, /, **kwds: object) -> None: # type: ignore[over ... # pragma: no cover -def test_get_constructor() -> None: - assert get_constructor("pandas[pyarrow]") == get_constructor("pandas[pyarrow]") +def test_get_backend_constructor() -> None: + assert get_backend_constructor("pandas[pyarrow]") == get_backend_constructor( + "pandas[pyarrow]" + ) -def test_get_constructor_invalid_name() -> None: +def test_get_backend_constructor_invalid_name() -> None: with pytest.raises(ValueError, match="Unknown constructor"): - get_constructor("not_a_backend") + get_backend_constructor("not_a_backend") -def test_prepare_constructors_exclude_only() -> None: - result = prepare_constructors(exclude=["pandas"]) +def test_prepare_backends_exclude_only() -> None: + result = prepare_backends(exclude=["pandas"]) names = {c.name for c in result} assert "pandas" not in names diff --git a/tests/translate/from_native_test.py b/tests/translate/from_native_test.py index 21bd7ce7b9..a0d94b99fb 100644 --- a/tests/translate/from_native_test.py +++ b/tests/translate/from_native_test.py @@ -30,7 +30,7 @@ import narwhals as nw from narwhals._utils import Version -from narwhals.testing.constructors import get_constructor +from narwhals.testing.constructors import get_backend_constructor from tests.utils import Constructor, maybe_get_modin_df if TYPE_CHECKING: @@ -294,7 +294,7 @@ def test_eager_only_lazy_dask(eager_only: Any, context: Any) -> None: def test_series_only_sqlframe() -> None: # pragma: no cover pytest.importorskip("sqlframe") - df = get_constructor("sqlframe")(data) + df = get_backend_constructor("sqlframe")(data) with pytest.raises(TypeError, match="Cannot only use `series_only`"): nw.from_native(df, series_only=True) # type: ignore[call-overload] @@ -315,7 +315,7 @@ def test_series_only_sqlframe() -> None: # pragma: no cover ) def test_eager_only_sqlframe(eager_only: Any, context: Any) -> None: # pragma: no cover pytest.importorskip("sqlframe") - df = get_constructor("sqlframe")(data) + df = get_backend_constructor("sqlframe")(data) with context: res = nw.from_native(df, eager_only=eager_only) From c7e2880b6f5c552709507d75d4b905579783c67a Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sat, 18 Apr 2026 22:55:59 +0200 Subject: [PATCH 03/11] fixup plugin --- narwhals/testing/pytest_plugin.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/narwhals/testing/pytest_plugin.py b/narwhals/testing/pytest_plugin.py index 34c9221207..22df94a5fa 100644 --- a/narwhals/testing/pytest_plugin.py +++ b/narwhals/testing/pytest_plugin.py @@ -71,7 +71,7 @@ def pytest_addoption(parser: pytest.Parser) -> None: # Escape hatch for downstream test suites that ship their own backend plugin. # When set, this plugin still adds the CLI options but stops parametrising the fixtures. group.addoption( - "--use-external-backend", + "--use-external-nw-backend", action="store_true", default=False, help=( @@ -100,23 +100,23 @@ def _select_backends(config: pytest.Config) -> list[FrameConstructor]: # pragma def pytest_generate_tests(metafunc: pytest.Metafunc) -> None: - if metafunc.config.getoption("use_external_backend"): # pragma: no cover + if metafunc.config.getoption("use_external_nw_backend"): # pragma: no cover return fixturenames = set(metafunc.fixturenames) if not fixturenames & { "nw_frame_constructor", - "nw_eager_frame_constructor", + "nw_eager_constructor", "nw_pandas_like_constructor", }: return selected = _select_backends(metafunc.config) - if "nw_eager_frame_constructor" in fixturenames: + if "nw_eager_constructor" in fixturenames: params = [c for c in selected if c.is_eager] ids = [c.name for c in params] - metafunc.parametrize("nw_eager_frame_constructor", params, ids=ids) + metafunc.parametrize("nw_eager_constructor", params, ids=ids) elif "nw_frame_constructor" in fixturenames: metafunc.parametrize( "nw_frame_constructor", selected, ids=[c.name for c in selected] From 1c2ce6b45e0359eba8688fe81b63ff7ecba7c4fd Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sat, 18 Apr 2026 22:56:49 +0200 Subject: [PATCH 04/11] regex brings you a long way :) --- .../is_narwhals_dataframe_test.py | 4 +- .../is_narwhals_lazyframe_test.py | 4 +- tests/dependencies/is_narwhals_series_test.py | 4 +- tests/dtypes/dtypes_test.py | 24 +-- tests/expr_and_series/abs_test.py | 8 +- tests/expr_and_series/all_horizontal_test.py | 48 ++--- tests/expr_and_series/any_all_test.py | 8 +- tests/expr_and_series/any_horizontal_test.py | 32 +-- tests/expr_and_series/any_value_test.py | 39 ++-- tests/expr_and_series/arithmetic_test.py | 72 +++---- tests/expr_and_series/binary_test.py | 6 +- tests/expr_and_series/cast_test.py | 113 ++++++----- .../cat/get_categories_test.py | 16 +- tests/expr_and_series/clip_test.py | 23 ++- tests/expr_and_series/coalesce_test.py | 22 +-- tests/expr_and_series/concat_str_test.py | 10 +- tests/expr_and_series/corr_test.py | 28 +-- tests/expr_and_series/cos_test.py | 8 +- tests/expr_and_series/count_test.py | 8 +- tests/expr_and_series/cum_count_test.py | 24 +-- tests/expr_and_series/cum_max_test.py | 73 +++---- tests/expr_and_series/cum_min_test.py | 81 ++++---- tests/expr_and_series/cum_prod_test.py | 33 ++-- tests/expr_and_series/cum_sum_test.py | 72 +++---- tests/expr_and_series/diff_test.py | 26 +-- .../expr_and_series/division_by_zero_test.py | 54 ++--- tests/expr_and_series/double_selected_test.py | 4 +- tests/expr_and_series/double_test.py | 8 +- tests/expr_and_series/drop_nulls_test.py | 16 +- .../dt/convert_time_zone_test.py | 52 ++--- .../dt/datetime_attributes_test.py | 48 +++-- .../dt/datetime_duration_test.py | 32 +-- tests/expr_and_series/dt/offset_by_test.py | 81 ++++---- .../dt/replace_time_zone_test.py | 44 ++--- tests/expr_and_series/dt/timestamp_test.py | 64 +++--- tests/expr_and_series/dt/to_string_test.py | 34 ++-- tests/expr_and_series/dt/truncate_test.py | 46 +++-- tests/expr_and_series/ewm_test.py | 30 +-- tests/expr_and_series/exclude_test.py | 4 +- tests/expr_and_series/exp_test.py | 8 +- tests/expr_and_series/fill_nan_test.py | 24 +-- tests/expr_and_series/fill_null_test.py | 116 +++++------ tests/expr_and_series/filter_test.py | 26 +-- tests/expr_and_series/first_last_test.py | 80 ++++---- tests/expr_and_series/floor_ceil_test.py | 16 +- tests/expr_and_series/format_test.py | 4 +- .../horizontal_broadcasts_test.py | 6 +- tests/expr_and_series/is_between_test.py | 24 +-- tests/expr_and_series/is_close_test.py | 60 +++--- tests/expr_and_series/is_duplicated_test.py | 16 +- tests/expr_and_series/is_finite_test.py | 37 ++-- .../expr_and_series/is_first_distinct_test.py | 37 ++-- tests/expr_and_series/is_in_test.py | 20 +- .../expr_and_series/is_last_distinct_test.py | 48 +++-- tests/expr_and_series/is_nan_test.py | 36 ++-- tests/expr_and_series/is_null_test.py | 8 +- tests/expr_and_series/is_unique_test.py | 27 +-- tests/expr_and_series/kurtosis_test.py | 14 +- tests/expr_and_series/len_test.py | 18 +- tests/expr_and_series/list/contains_test.py | 14 +- tests/expr_and_series/list/get_test.py | 49 ++--- tests/expr_and_series/list/len_test.py | 18 +- tests/expr_and_series/list/max_test.py | 18 +- tests/expr_and_series/list/mean_test.py | 18 +- tests/expr_and_series/list/median_test.py | 32 +-- tests/expr_and_series/list/min_test.py | 18 +- tests/expr_and_series/list/sort_test.py | 22 +-- tests/expr_and_series/list/sum_test.py | 20 +- tests/expr_and_series/list/unique_test.py | 16 +- tests/expr_and_series/lit_test.py | 54 ++--- tests/expr_and_series/log_test.py | 8 +- tests/expr_and_series/map_batches_test.py | 26 +-- tests/expr_and_series/max_horizontal_test.py | 8 +- tests/expr_and_series/max_test.py | 8 +- tests/expr_and_series/mean_horizontal_test.py | 14 +- tests/expr_and_series/mean_test.py | 8 +- tests/expr_and_series/median_test.py | 24 +-- tests/expr_and_series/min_horizontal_test.py | 8 +- tests/expr_and_series/min_test.py | 8 +- tests/expr_and_series/mode_test.py | 38 ++-- tests/expr_and_series/n_unique_test.py | 26 +-- tests/expr_and_series/name/keep_test.py | 12 +- tests/expr_and_series/name/map_test.py | 14 +- tests/expr_and_series/name/prefix_test.py | 14 +- tests/expr_and_series/name/suffix_test.py | 14 +- .../expr_and_series/name/to_lowercase_test.py | 14 +- .../expr_and_series/name/to_uppercase_test.py | 14 +- tests/expr_and_series/nth_test.py | 8 +- tests/expr_and_series/null_count_test.py | 8 +- tests/expr_and_series/operators_test.py | 42 ++-- .../order_dependent_lazy_test.py | 4 +- tests/expr_and_series/over_pushdown_test.py | 6 +- tests/expr_and_series/over_test.py | 174 ++++++++-------- tests/expr_and_series/pipe_test.py | 8 +- tests/expr_and_series/quantile_test.py | 18 +- tests/expr_and_series/rank_test.py | 110 +++++------ tests/expr_and_series/reduction_test.py | 26 +-- tests/expr_and_series/replace_strict_test.py | 97 ++++----- tests/expr_and_series/rolling_mean_test.py | 32 +-- tests/expr_and_series/rolling_std_test.py | 38 ++-- tests/expr_and_series/rolling_sum_test.py | 40 ++-- tests/expr_and_series/rolling_var_test.py | 38 ++-- tests/expr_and_series/round_test.py | 8 +- tests/expr_and_series/sample_test.py | 8 +- tests/expr_and_series/shift_test.py | 30 +-- tests/expr_and_series/sin_test.py | 8 +- tests/expr_and_series/skew_test.py | 20 +- tests/expr_and_series/sqrt_test.py | 8 +- tests/expr_and_series/std_test.py | 10 +- tests/expr_and_series/str/contains_test.py | 40 ++-- tests/expr_and_series/str/head_test.py | 8 +- tests/expr_and_series/str/len_chars_test.py | 8 +- tests/expr_and_series/str/pad_test.py | 32 +-- tests/expr_and_series/str/replace_test.py | 92 +++++---- tests/expr_and_series/str/slice_test.py | 8 +- tests/expr_and_series/str/split_test.py | 23 +-- .../str/starts_with_ends_with_test.py | 16 +- tests/expr_and_series/str/strip_chars_test.py | 10 +- tests/expr_and_series/str/tail_test.py | 8 +- tests/expr_and_series/str/to_date_test.py | 48 +++-- tests/expr_and_series/str/to_datetime_test.py | 65 +++--- .../expr_and_series/str/to_titlecase_test.py | 12 +- .../str/to_uppercase_to_lowercase_test.py | 20 +- tests/expr_and_series/str/zfill_test.py | 22 ++- tests/expr_and_series/struct_/field_test.py | 22 ++- tests/expr_and_series/struct_test.py | 70 +++---- tests/expr_and_series/sum_horizontal_test.py | 22 +-- tests/expr_and_series/sum_test.py | 8 +- tests/expr_and_series/unary_test.py | 42 ++-- tests/expr_and_series/unique_test.py | 22 +-- tests/expr_and_series/var_test.py | 10 +- tests/expr_and_series/when_test.py | 184 +++++++++-------- tests/expression_parsing_test.py | 24 +-- tests/frame/add_test.py | 6 +- tests/frame/array_dunder_test.py | 22 +-- tests/frame/clone_test.py | 4 +- tests/frame/collect_test.py | 48 ++--- tests/frame/columns_test.py | 8 +- tests/frame/concat_test.py | 35 ++-- tests/frame/double_test.py | 4 +- tests/frame/drop_nulls_test.py | 8 +- tests/frame/drop_test.py | 18 +- tests/frame/eq_test.py | 6 +- tests/frame/estimated_size_test.py | 4 +- tests/frame/explode_test.py | 38 ++-- tests/frame/filter_test.py | 66 ++++--- tests/frame/from_dict_test.py | 18 +- tests/frame/get_column_test.py | 4 +- tests/frame/getitem_test.py | 128 ++++++------ tests/frame/group_by_test.py | 187 ++++++++++-------- tests/frame/head_test.py | 4 +- tests/frame/invalid_test.py | 4 +- tests/frame/is_duplicated_test.py | 8 +- tests/frame/is_empty_test.py | 4 +- tests/frame/is_unique_test.py | 8 +- tests/frame/item_test.py | 8 +- tests/frame/join_test.py | 183 +++++++++-------- tests/frame/lazy_test.py | 30 +-- tests/frame/len_test.py | 4 +- tests/frame/null_count_test.py | 4 +- tests/frame/pipe_test.py | 4 +- tests/frame/pivot_test.py | 44 ++--- tests/frame/rename_test.py | 4 +- tests/frame/row_test.py | 6 +- tests/frame/rows_test.py | 26 +-- tests/frame/sample_test.py | 14 +- tests/frame/schema_test.py | 26 +-- tests/frame/select_test.py | 44 +++-- tests/frame/shape_test.py | 4 +- tests/frame/sink_parquet_test.py | 8 +- tests/frame/sort_test.py | 8 +- tests/frame/tail_test.py | 4 +- tests/frame/to_arrow_test.py | 4 +- tests/frame/to_dict_test.py | 8 +- tests/frame/to_native_test.py | 4 +- tests/frame/to_numpy_test.py | 12 +- tests/frame/to_pandas_test.py | 10 +- tests/frame/to_polars_test.py | 4 +- tests/frame/top_k_test.py | 20 +- tests/frame/unique_test.py | 52 ++--- tests/frame/unpivot_test.py | 24 +-- tests/frame/with_columns_sequence_test.py | 4 +- tests/frame/with_columns_test.py | 48 ++--- tests/frame/with_row_index_test.py | 35 ++-- tests/frame/write_csv_test.py | 10 +- tests/frame/write_parquet_test.py | 4 +- tests/from_dict_test.py | 18 +- tests/from_numpy_test.py | 20 +- tests/joblib_test.py | 10 +- tests/modern_polars/ewm_mean_test.py | 8 +- tests/modern_polars/filter_test.py | 4 +- tests/modern_polars/method_chaining_2_test.py | 4 +- tests/modern_polars/method_chaining_test.py | 16 +- tests/modern_polars/performance_test.py | 8 +- tests/modern_polars/pivot_test.py | 8 +- tests/modern_polars/unpivot_test.py | 4 +- tests/namespace_test.py | 4 +- tests/new_series_test.py | 4 +- ...erve_pandas_like_columns_name_attr_test.py | 10 +- tests/read_scan_test.py | 18 +- tests/selectors_test.py | 92 +++++---- tests/series_only/__contains___test.py | 12 +- tests/series_only/__iter___test.py | 6 +- tests/series_only/alias_rename_test.py | 4 +- tests/series_only/arg_max_test.py | 8 +- tests/series_only/arg_min_test.py | 8 +- tests/series_only/arg_true_test.py | 4 +- tests/series_only/array_dunder_test.py | 20 +- tests/series_only/cast_test.py | 12 +- tests/series_only/gather_every_test.py | 4 +- tests/series_only/getitem_test.py | 26 +-- tests/series_only/head_test.py | 4 +- tests/series_only/hist_test.py | 42 ++-- tests/series_only/is_empty_test.py | 4 +- .../is_ordered_categorical_test.py | 4 +- tests/series_only/is_sorted_test.py | 10 +- tests/series_only/item_test.py | 8 +- tests/series_only/scatter_test.py | 8 +- tests/series_only/shape_test.py | 6 +- tests/series_only/sort_test.py | 11 +- tests/series_only/tail_test.py | 4 +- tests/series_only/to_arrow_test.py | 12 +- tests/series_only/to_dummy_test.py | 24 ++- tests/series_only/to_frame_test.py | 4 +- tests/series_only/to_list_test.py | 4 +- tests/series_only/to_native_test.py | 6 +- tests/series_only/to_numpy_test.py | 18 +- tests/series_only/to_pandas_test.py | 8 +- tests/series_only/to_polars_test.py | 4 +- tests/series_only/value_counts_test.py | 8 +- tests/series_only/zip_with_test.py | 20 +- tests/testing/assert_frame_equal_test.py | 56 +++--- tests/testing/assert_series_equal_test.py | 64 +++--- tests/testing/plugin_test.py | 18 +- tests/translate/from_native_test.py | 17 +- tests/translate/get_native_namespace_test.py | 12 +- tests/translate/to_native_test.py | 8 +- tests/utils.py | 14 +- tests/v1_test.py | 54 ++--- tests/v2_test.py | 30 +-- 240 files changed, 3261 insertions(+), 2867 deletions(-) diff --git a/tests/dependencies/is_narwhals_dataframe_test.py b/tests/dependencies/is_narwhals_dataframe_test.py index aeedf15981..4880a254d0 100644 --- a/tests/dependencies/is_narwhals_dataframe_test.py +++ b/tests/dependencies/is_narwhals_dataframe_test.py @@ -9,8 +9,8 @@ from tests.utils import ConstructorEager -def test_is_narwhals_dataframe(constructor_eager: ConstructorEager) -> None: - df = constructor_eager({"col1": [1, 2], "col2": [3, 4]}) +def test_is_narwhals_dataframe(nw_eager_constructor: ConstructorEager) -> None: + df = nw_eager_constructor({"col1": [1, 2], "col2": [3, 4]}) assert is_narwhals_dataframe(nw.from_native(df)) assert not is_narwhals_dataframe(df) diff --git a/tests/dependencies/is_narwhals_lazyframe_test.py b/tests/dependencies/is_narwhals_lazyframe_test.py index 0e4c6e1bd9..96be4bc4cf 100644 --- a/tests/dependencies/is_narwhals_lazyframe_test.py +++ b/tests/dependencies/is_narwhals_lazyframe_test.py @@ -10,8 +10,8 @@ from tests.utils import Constructor -def test_is_narwhals_lazyframe(constructor: Constructor) -> None: - lf = constructor({"a": [1, 2, 3]}) +def test_is_narwhals_lazyframe(nw_frame_constructor: Constructor) -> None: + lf = nw_frame_constructor({"a": [1, 2, 3]}) assert is_narwhals_lazyframe(nw.from_native(lf).lazy()) assert not is_narwhals_lazyframe(lf) diff --git a/tests/dependencies/is_narwhals_series_test.py b/tests/dependencies/is_narwhals_series_test.py index 659696d108..b3b01bb848 100644 --- a/tests/dependencies/is_narwhals_series_test.py +++ b/tests/dependencies/is_narwhals_series_test.py @@ -9,8 +9,8 @@ from tests.utils import ConstructorEager -def test_is_narwhals_series(constructor_eager: ConstructorEager) -> None: - df = constructor_eager({"col1": [1, 2], "col2": [3, 4]}) +def test_is_narwhals_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw_eager_constructor({"col1": [1, 2], "col2": [3, 4]}) assert is_narwhals_series(nw.from_native(df, eager_only=True)["col1"]) assert not is_narwhals_series(nw.from_native(df, eager_only=True)["col1"].to_native()) diff --git a/tests/dtypes/dtypes_test.py b/tests/dtypes/dtypes_test.py index a233f955f3..3d8a0c658d 100644 --- a/tests/dtypes/dtypes_test.py +++ b/tests/dtypes/dtypes_test.py @@ -146,21 +146,23 @@ def test_struct_hashes() -> None: assert len({hash(tp) for tp in (dtypes)}) == 3 -def test_2d_array(constructor: Constructor, request: pytest.FixtureRequest) -> None: +def test_2d_array( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: version_conditions = [ (PANDAS_VERSION < (2, 2), "Requires pandas 2.2+ for 2D array support"), ( - "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,), + "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,), "PyArrow 14+ required for 2D array support", ), ] for condition, reason in version_conditions: if condition: pytest.skip(reason) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): pytest.importorskip("pyarrow") - if any(x in str(constructor) for x in ("dask", "cudf", "pyspark")): + if any(x in str(nw_frame_constructor) for x in ("dask", "cudf", "pyspark")): request.applymarker( pytest.mark.xfail( reason="2D array operations not supported in these backends" @@ -168,7 +170,7 @@ def test_2d_array(constructor: Constructor, request: pytest.FixtureRequest) -> N ) data = {"a": [[[1, 2], [3, 4], [5, 6]]]} - df = nw.from_native(constructor(data)).with_columns( + df = nw.from_native(nw_frame_constructor(data)).with_columns( a=nw.col("a").cast(nw.Array(nw.Int64(), (3, 2))) ) assert df.collect_schema()["a"] == nw.Array(nw.Int64(), (3, 2)) @@ -413,19 +415,19 @@ def test_huge_int_to_native() -> None: ) def test_cast_decimal_to_native( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, precision: int | None, scale: int, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail(reason="Unsupported dtype")) - if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip(reason="too old to convert to decimal") data = {"a": [1.1, 2.2, 3.3]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) if df.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) @@ -617,13 +619,13 @@ def test_dtype_base_type_nested(nested_dtype: NestedOrEnumDType) -> None: ], ) def test_pandas_datetime_ignored_time_unit_warns( - constructor_pandas_like: ConstructorPandasLike, + nw_pandas_like_constructor: ConstructorPandasLike, dtype: nw.Datetime | type[nw.Datetime], context: AbstractContextManager[Any], ) -> None: data = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} expr = nw.col("a").cast(dtype) - df = nw.from_native(constructor_pandas_like(data)) + df = nw.from_native(nw_pandas_like_constructor(data)) ctx = does_not_warn() if PANDAS_VERSION >= (2,) else context with ctx: df.select(expr) diff --git a/tests/expr_and_series/abs_test.py b/tests/expr_and_series/abs_test.py index 547ff9d8dc..99d2dcb186 100644 --- a/tests/expr_and_series/abs_test.py +++ b/tests/expr_and_series/abs_test.py @@ -4,15 +4,15 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_abs(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, -4, 5]})) +def test_abs(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, -4, 5]})) result = df.select(b=nw.col("a").abs()) expected = {"b": [1, 2, 3, 4, 5]} assert_equal_data(result, expected) -def test_abs_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [1, 2, 3, -4, 5]}), eager_only=True) +def test_abs_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, -4, 5]}), eager_only=True) result = {"b": df["a"].abs()} expected = {"b": [1, 2, 3, 4, 5]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/all_horizontal_test.py b/tests/expr_and_series/all_horizontal_test.py index d980b3def3..50accfe523 100644 --- a/tests/expr_and_series/all_horizontal_test.py +++ b/tests/expr_and_series/all_horizontal_test.py @@ -9,50 +9,52 @@ from tests.utils import POLARS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_allh(constructor: Constructor) -> None: +def test_allh(nw_frame_constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(all=nw.all_horizontal("a", nw.col("b"), ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) -def test_all_ignore_nulls(constructor: Constructor) -> None: - if "dask" in str(constructor): +def test_all_ignore_nulls(nw_frame_constructor: Constructor) -> None: + if "dask" in str(nw_frame_constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(any=nw.all_horizontal("a", "b", ignore_nulls=True)) expected = [True, True, False] assert_equal_data(result, {"any": expected}) -def test_allh_kleene(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "cudf" in str(constructor): +def test_allh_kleene( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() context = ( pytest.raises(ValueError, match="ignore_nulls") - if "pandas_constructor" in str(constructor) + if "pandas_constructor" in str(nw_frame_constructor) else does_not_raise() ) data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with context: result = df.select(all=nw.all_horizontal("a", "b", ignore_nulls=False)) expected = [True, None, False] assert_equal_data(result, {"all": expected}) -def test_anyh_dask(constructor: Constructor) -> None: - if "dask" not in str(constructor): +def test_anyh_dask(nw_frame_constructor: Constructor) -> None: + if "dask" not in str(nw_frame_constructor): pytest.skip() import dask.dataframe as dd import pandas as pd @@ -74,18 +76,18 @@ def test_anyh_dask(constructor: Constructor) -> None: assert_equal_data(result, {"all": expected}) -def test_allh_series(constructor_eager: ConstructorEager) -> None: +def test_allh_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(all=nw.all_horizontal(df["a"], df["b"], ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) -def test_allh_all(constructor: Constructor) -> None: +def test_allh_all(nw_frame_constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(all=nw.all_horizontal(nw.all(), ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) @@ -94,11 +96,11 @@ def test_allh_all(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_allh_nth(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 0): +def test_allh_nth(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0): pytest.skip() data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.all_horizontal(nw.nth(0, 1), ignore_nulls=True)) expected = {"a": [False, False, True]} assert_equal_data(result, expected) @@ -107,13 +109,13 @@ def test_allh_nth(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_allh_iterator(constructor: Constructor) -> None: +def test_allh_iterator(nw_frame_constructor: Constructor) -> None: def iter_eq(items: Any, /) -> Any: for column, value in items: yield nw.col(column) == value data = {"a": [1, 2, 3, 3, 3], "b": ["b", "b", "a", "a", "b"]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) expr_items = [("a", 3), ("b", "b")] expected = {"a": [3], "b": ["b"]} @@ -128,9 +130,9 @@ def iter_eq(items: Any, /) -> Any: assert_equal_data(df.filter(lazy), expected) -def test_horizontal_expressions_empty(constructor: Constructor) -> None: +def test_horizontal_expressions_empty(nw_frame_constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises( ValueError, match=r"At least one expression must be passed.*all_horizontal" ): diff --git a/tests/expr_and_series/any_all_test.py b/tests/expr_and_series/any_all_test.py index 6b6cc6e35f..6e195f4fec 100644 --- a/tests/expr_and_series/any_all_test.py +++ b/tests/expr_and_series/any_all_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_any_all(constructor: Constructor) -> None: +def test_any_all(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [True, False, True], "b": [True, True, True], @@ -22,9 +22,9 @@ def test_any_all(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_any_all_series(constructor_eager: ConstructorEager) -> None: +def test_any_all_series(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager( + nw_eager_constructor( { "a": [True, False, True], "b": [True, True, True], diff --git a/tests/expr_and_series/any_horizontal_test.py b/tests/expr_and_series/any_horizontal_test.py index 04f0cba76c..f00e679336 100644 --- a/tests/expr_and_series/any_horizontal_test.py +++ b/tests/expr_and_series/any_horizontal_test.py @@ -8,50 +8,52 @@ from tests.utils import Constructor, assert_equal_data -def test_anyh(constructor: Constructor) -> None: +def test_anyh(nw_frame_constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(any=nw.any_horizontal(nw.col("a"), "b", ignore_nulls=True)) expected = {"any": [False, True, True]} assert_equal_data(result, expected) -def test_anyh_kleene(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "cudf" in str(constructor): +def test_anyh_kleene( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() context = ( pytest.raises(ValueError, match="ignore_nulls") - if "pandas_constructor" in str(constructor) + if "pandas_constructor" in str(nw_frame_constructor) else does_not_raise() ) data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with context: result = df.select(any=nw.any_horizontal("a", "b", ignore_nulls=False)) expected = [True, True, None] assert_equal_data(result, {"any": expected}) -def test_anyh_ignore_nulls(constructor: Constructor) -> None: - if "dask" in str(constructor): +def test_anyh_ignore_nulls(nw_frame_constructor: Constructor) -> None: + if "dask" in str(nw_frame_constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(any=nw.any_horizontal("a", "b", ignore_nulls=True)) expected = [True, True, False] assert_equal_data(result, {"any": expected}) -def test_anyh_dask(constructor: Constructor) -> None: - if "dask" not in str(constructor): +def test_anyh_dask(nw_frame_constructor: Constructor) -> None: + if "dask" not in str(nw_frame_constructor): pytest.skip() import dask.dataframe as dd import pandas as pd @@ -73,12 +75,12 @@ def test_anyh_dask(constructor: Constructor) -> None: assert_equal_data(result, {"any": expected}) -def test_anyh_all(constructor: Constructor) -> None: - if "dask" in str(constructor): +def test_anyh_all(nw_frame_constructor: Constructor) -> None: + if "dask" in str(nw_frame_constructor): # Can't use `ignore_nulls` for NumPy-backed Dask, test it separately below pytest.skip() data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(any=nw.any_horizontal(nw.all(), ignore_nulls=False)) expected = {"any": [False, True, True]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/any_value_test.py b/tests/expr_and_series/any_value_test.py index e665fbd03c..3ee2367989 100644 --- a/tests/expr_and_series/any_value_test.py +++ b/tests/expr_and_series/any_value_test.py @@ -19,13 +19,16 @@ @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_expr( - constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + *, + ignore_nulls: bool, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) # Aggregation result = ( @@ -33,7 +36,7 @@ def test_any_value_expr( ) assert result.shape == (1, 2) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): reason = "broadcast requires `over`, which requires DuckDB 1.3.0" pytest.skip(reason=reason) @@ -66,9 +69,9 @@ def test_any_value_expr( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_series( - constructor_eager: ConstructorEager, *, ignore_nulls: bool + nw_eager_constructor: ConstructorEager, *, ignore_nulls: bool ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = { "a": [df["a"].any_value(ignore_nulls=ignore_nulls)], @@ -84,16 +87,19 @@ def test_any_value_series( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_group_by( - constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + *, + ignore_nulls: bool, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0): reason = "too old" pytest.skip(reason) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) if ignore_nulls and df.implementation.is_pandas_like(): reason = "not implemented" @@ -118,21 +124,24 @@ def test_any_value_group_by( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_over( - constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + *, + ignore_nulls: bool, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): reason = "`over` requires DuckDB 1.3.0" pytest.skip(reason=reason) - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0): reason = "too old" pytest.skip(reason) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) if ignore_nulls and df.implementation.is_pandas_like(): reason = "not implemented" diff --git a/tests/expr_and_series/arithmetic_test.py b/tests/expr_and_series/arithmetic_test.py index af0c464e5b..1aee0bd662 100644 --- a/tests/expr_and_series/arithmetic_test.py +++ b/tests/expr_and_series/arithmetic_test.py @@ -34,18 +34,18 @@ def test_arithmetic_expr( attr: str, rhs: Any, expected: list[Any], - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(constructor) and attr == "__floordiv__": + if "duckdb" in str(nw_frame_constructor) and attr == "__floordiv__": request.applymarker(pytest.mark.xfail) if attr == "__mod__" and any( - x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 3.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a"), attr)(rhs)) assert_equal_data(result, {"a": expected}) @@ -66,17 +66,17 @@ def test_right_arithmetic_expr( attr: str, rhs: Any, expected: list[Any], - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "dask" in str(constructor) and DASK_VERSION < (2024, 10): + if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): pytest.skip() if attr == "__rmod__" and any( - x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a"), attr)(rhs)) assert_equal_data(result, {"literal": expected}) @@ -98,16 +98,16 @@ def test_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(getattr(df["a"], attr)(rhs)) assert_equal_data(result, {"a": expected}) @@ -128,29 +128,29 @@ def test_right_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__rmod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = getattr(df["a"], attr)(rhs) assert result_series.name == "a" assert_equal_data({"a": result_series}, {"a": expected}) def test_truediv_same_dims( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor_eager): + if "polars" in str(nw_eager_constructor): # https://github.com/pola-rs/polars/issues/17760 request.applymarker(pytest.mark.xfail) - s_left = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] - s_right = nw.from_native(constructor_eager({"a": [2, 2, 1]}), eager_only=True)["a"] + s_left = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + s_right = nw.from_native(nw_eager_constructor({"a": [2, 2, 1]}), eager_only=True)["a"] result = s_left / s_right assert_equal_data({"a": result}, {"a": [0.5, 1.0, 3.0]}) result = s_left.__rtruediv__(s_right) @@ -160,13 +160,15 @@ def test_truediv_same_dims( @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") @pytest.mark.slow -def test_floordiv(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(constructor_eager) for x in ["modin", "cudf"]): +def test_floordiv( + nw_eager_constructor: ConstructorEager, *, left: int, right: int +) -> None: + if any(x in str(nw_eager_constructor) for x in ["modin", "cudf"]): # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left // right]} - result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( nw.col("a") // right ) assert_equal_data(result, expected) @@ -175,14 +177,14 @@ def test_floordiv(constructor_eager: ConstructorEager, *, left: int, right: int) @pytest.mark.slow @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") -def test_mod(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(constructor_eager) for x in ["pandas_pyarrow", "modin", "cudf"]): +def test_mod(nw_eager_constructor: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin", "cudf"]): # pandas[pyarrow] does not implement mod # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left % right]} - result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( nw.col("a") % right ) assert_equal_data(result, expected) @@ -205,20 +207,20 @@ def test_arithmetic_expr_left_literal( attr: str, lhs: Any, expected: list[Any], - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if ("duckdb" in str(constructor) and attr == "__floordiv__") or ( - "dask" in str(constructor) and DASK_VERSION < (2024, 10) + if ("duckdb" in str(nw_frame_constructor) and attr == "__floordiv__") or ( + "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10) ): request.applymarker(pytest.mark.xfail) if attr == "__mod__" and any( - x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 4.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(lhs, attr)(nw.col("a"))) assert_equal_data(result, {"literal": expected}) @@ -240,25 +242,25 @@ def test_arithmetic_series_left_literal( attr: str, lhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 4.0]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(getattr(lhs, attr)(nw.col("a"))) assert_equal_data(result, {"literal": expected}) -def test_std_broadcating(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_std_broadcating(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): # `std(ddof=2)` fails for duckdb here pytest.skip() - df = nw.from_native(constructor({"a": [1, 2, 3]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) result = df.with_columns(b=nw.col("a").std()).sort("a") expected = {"a": [1, 2, 3], "b": [1.0, 1.0, 1.0]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/binary_test.py b/tests/expr_and_series/binary_test.py index 6140ead120..c64ca8e67f 100644 --- a/tests/expr_and_series/binary_test.py +++ b/tests/expr_and_series/binary_test.py @@ -6,11 +6,11 @@ from tests.utils import DASK_VERSION, Constructor, assert_equal_data -def test_expr_binary(constructor: Constructor) -> None: - if "dask" in str(constructor) and DASK_VERSION < (2024, 10): +def test_expr_binary(nw_frame_constructor: Constructor) -> None: + if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) result = nw.from_native(df_raw).with_columns( a=(1 + 3 * nw.col("a")) * (1 / nw.col("a")), b=nw.col("z") / (2 - nw.col("b")), diff --git a/tests/expr_and_series/cast_test.py b/tests/expr_and_series/cast_test.py index 90282ea596..581629863a 100644 --- a/tests/expr_and_series/cast_test.py +++ b/tests/expr_and_series/cast_test.py @@ -65,17 +65,17 @@ @pytest.mark.filterwarnings("ignore:casting period[M] values to int64:FutureWarning") -def test_cast(constructor: Constructor) -> None: - if "pyarrow_table_constructor" in str(constructor) and PYARROW_VERSION <= ( +def test_cast(nw_frame_constructor: Constructor) -> None: + if "pyarrow_table_constructor" in str(nw_frame_constructor) and PYARROW_VERSION <= ( 15, ): # pragma: no cover pytest.skip() - if "pyspark" in str(constructor): + if "pyspark" in str(nw_frame_constructor): incompatible_columns = SPARK_LIKE_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "duckdb" in str(constructor): + elif "duckdb" in str(nw_frame_constructor): incompatible_columns = DUCKDB_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "ibis" in str(constructor): + elif "ibis" in str(nw_frame_constructor): incompatible_columns = IBIS_INCOMPATIBLE_COLUMNS # pragma: no cover else: incompatible_columns = set() @@ -83,7 +83,7 @@ def test_cast(constructor: Constructor) -> None: data = {c: v for c, v in DATA.items() if c not in incompatible_columns} schema = {c: t for c, t in SCHEMA.items() if c not in incompatible_columns} - df = nw.from_native(constructor(data)).select( + df = nw.from_native(nw_frame_constructor(data)).select( nw.col(col_).cast(dtype) for col_, dtype in schema.items() ) @@ -112,7 +112,10 @@ def test_cast(constructor: Constructor) -> None: ).collect_schema() for (key, ltype), rtype in zip(result.items(), cast_map.values()): - if "modin_constructor" in str(constructor) and key in MODIN_XFAIL_COLUMNS: + if ( + "modin_constructor" in str(nw_frame_constructor) + and key in MODIN_XFAIL_COLUMNS + ): # TODO(unassigned): in modin we end up with `' None: def test_cast_series( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table_constructor" in str(constructor_eager) and PYARROW_VERSION <= ( + if "pyarrow_table_constructor" in str(nw_eager_constructor) and PYARROW_VERSION <= ( 15, ): # pragma: no cover request.applymarker(pytest.mark.xfail) df = ( - nw.from_native(constructor_eager(DATA)) + nw.from_native(nw_eager_constructor(DATA)) .select(nw.col(key).cast(value) for key, value in SCHEMA.items()) .lazy() .collect() @@ -156,7 +159,10 @@ def test_cast_series( result = df.select(df[col_].cast(dtype) for col_, dtype in cast_map.items()).schema for (key, ltype), rtype in zip(result.items(), cast_map.values()): - if "modin_constructor" in str(constructor_eager) and key in MODIN_XFAIL_COLUMNS: + if ( + "modin_constructor" in str(nw_eager_constructor) + and key in MODIN_XFAIL_COLUMNS + ): # TODO(unassigned): in modin we end up with `' None: def test_cast_raises_for_unknown_dtype( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(constructor): + if "duckdb" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (15,): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (15,): # Unsupported cast from string to dictionary using function cast_dictionary request.applymarker(pytest.mark.xfail) - if "pyspark" in str(constructor): + if "pyspark" in str(nw_frame_constructor): incompatible_columns = SPARK_LIKE_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "ibis" in str(constructor): + elif "ibis" in str(nw_frame_constructor): incompatible_columns = IBIS_INCOMPATIBLE_COLUMNS # pragma: no cover else: incompatible_columns = set() @@ -195,7 +201,7 @@ def test_cast_raises_for_unknown_dtype( data = {k: v for k, v in DATA.items() if k not in incompatible_columns} schema = {k: v for k, v in SCHEMA.items() if k not in incompatible_columns} - df = nw.from_native(constructor(data)).select( + df = nw.from_native(nw_frame_constructor(data)).select( nw.col(key).cast(value) for key, value in schema.items() ) @@ -207,18 +213,21 @@ class Banana: def test_cast_datetime_tz_aware( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - "dask" in str(constructor) - or "duckdb" in str(constructor) - or "cudf" in str(constructor) # https://github.com/rapidsai/cudf/issues/16973 - or "pyspark" in str(constructor) - or "ibis" in str(constructor) + "dask" in str(nw_frame_constructor) + or "duckdb" in str(nw_frame_constructor) + or "cudf" + in str(nw_frame_constructor) # https://github.com/rapidsai/cudf/issues/16973 + or "pyspark" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) request.applymarker( - pytest.mark.xfail(is_pyarrow_windows_no_tzdata(constructor), reason="no tzdata") + pytest.mark.xfail( + is_pyarrow_windows_no_tzdata(nw_frame_constructor), reason="no tzdata" + ) ) data = { @@ -231,7 +240,7 @@ def test_cast_datetime_tz_aware( "date": ["2024-01-01 01:00:00", "2024-01-02 01:00:00", "2024-01-03 01:00:00"] } dtype = nw.Datetime(time_unit_compat("ms", request), time_zone="Europe/Rome") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("date").cast(dtype).cast(nw.String()).str.slice(offset=0, length=19) ) @@ -239,16 +248,18 @@ def test_cast_datetime_tz_aware( def test_cast_datetime_utc( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - "dask" in str(constructor) + "dask" in str(nw_frame_constructor) # https://github.com/eakmanrq/sqlframe/issues/406 - or "sqlframe" in str(constructor) + or "sqlframe" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) request.applymarker( - pytest.mark.xfail(is_pyarrow_windows_no_tzdata(constructor), reason="no tzdata") + pytest.mark.xfail( + is_pyarrow_windows_no_tzdata(nw_frame_constructor), reason="no tzdata" + ) ) data = { @@ -261,18 +272,20 @@ def test_cast_datetime_utc( "date": ["2024-01-01 00:00:00", "2024-01-02 00:00:00", "2024-01-03 00:00:00"] } dtype = nw.Datetime(time_unit_compat("us", request), time_zone="UTC") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("date").cast(dtype).cast(nw.String()).str.slice(offset=0, length=19) ) assert_equal_data(result, expected) -def test_cast_struct(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_cast_struct( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") @@ -281,9 +294,9 @@ def test_cast_struct(request: pytest.FixtureRequest, constructor: Constructor) - [nw.Field("movie", nw.String()), nw.Field("rating", nw.Float64())] ) - if "spark" in str(constructor): + if "spark" in str(nw_frame_constructor): data = {"movie": ["Cars", "Toy Story"], "rating": [4.5, 4.9]} - dframe = nw.from_native(constructor(data)).select( + dframe = nw.from_native(nw_frame_constructor(data)).select( a=nw.struct("movie", "rating").cast(from_dtype) ) @@ -291,7 +304,9 @@ def test_cast_struct(request: pytest.FixtureRequest, constructor: Constructor) - data = { "a": [{"movie": "Cars", "rating": 4.5}, {"movie": "Toy Story", "rating": 4.9}] } - dframe = nw.from_native(constructor(data)).select(nw.col("a").cast(from_dtype)) + dframe = nw.from_native(nw_frame_constructor(data)).select( + nw.col("a").cast(from_dtype) + ) to_dtype = nw.Struct( [nw.Field("movie", nw.String()), nw.Field("rating", nw.Float32())] @@ -300,42 +315,48 @@ def test_cast_struct(request: pytest.FixtureRequest, constructor: Constructor) - assert result.collect_schema() == {"a": to_dtype} -def test_raise_if_polars_dtype(constructor: Constructor) -> None: +def test_raise_if_polars_dtype(nw_frame_constructor: Constructor) -> None: pytest.importorskip("polars") import polars as pl for dtype in [pl.String, pl.String()]: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(TypeError, match="Expected Narwhals dtype, got:"): df.select(nw.col("a").cast(dtype)) # type: ignore[arg-type] -def test_cast_time(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if "pandas" in str(constructor): +def test_cast_time( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if any(backend in str(constructor) for backend in ("dask", "pyspark", "cudf")): + if any( + backend in str(nw_frame_constructor) for backend in ("dask", "pyspark", "cudf") + ): request.applymarker(pytest.mark.xfail) data = {"a": [time(12, 0, 0), time(12, 0, 5)]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").cast(nw.Time())) assert result.collect_schema() == {"a": nw.Time()} -def test_cast_binary(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if "pandas" in str(constructor): +def test_cast_binary( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if any(backend in str(constructor) for backend in ("cudf", "dask")): + if any(backend in str(nw_frame_constructor) for backend in ("cudf", "dask")): request.applymarker(pytest.mark.xfail) data = {"a": ["test1", "test2"]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( "a", b=nw.col("a").cast(nw.Binary()), diff --git a/tests/expr_and_series/cat/get_categories_test.py b/tests/expr_and_series/cat/get_categories_test.py index 6f984ff7ce..85bb42be94 100644 --- a/tests/expr_and_series/cat/get_categories_test.py +++ b/tests/expr_and_series/cat/get_categories_test.py @@ -10,15 +10,15 @@ def test_get_categories_eager( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < (15, 0, 0): + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < (15, 0, 0): pytest.skip() - if "polars" in str(constructor_eager): + if "polars" in str(nw_eager_constructor): reason = "https://github.com/narwhals-dev/narwhals/issues/3097" request.applymarker(pytest.mark.xfail(reason=reason, strict=False)) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) df = df.select(nw.col("a").cast(nw.Categorical)) expected = {"a": ["one", "two"]} @@ -30,16 +30,16 @@ def test_get_categories_eager( def test_get_categories_lazy( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < (15, 0, 0): + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < (15, 0, 0): pytest.skip() - if "polars" in str(constructor_eager): + if "polars" in str(nw_eager_constructor): reason = "https://github.com/narwhals-dev/narwhals/issues/3097" request.applymarker(pytest.mark.xfail(reason=reason, strict=False)) - df = nw.from_native(constructor_eager(data)).lazy() + df = nw.from_native(nw_eager_constructor(data)).lazy() expr = nw.col("a").cast(nw.Categorical).cat.get_categories() msg = "Length-changing expressions are not supported for use in LazyFrame" with pytest.raises(InvalidOperationError, match=msg): diff --git a/tests/expr_and_series/clip_test.py b/tests/expr_and_series/clip_test.py index 382133f23c..f2941a2ea7 100644 --- a/tests/expr_and_series/clip_test.py +++ b/tests/expr_and_series/clip_test.py @@ -18,16 +18,19 @@ ], ) def test_clip_expr( - constructor: Constructor, lower: int | None, upper: int | None, expected: list[int] + nw_frame_constructor: Constructor, + lower: int | None, + upper: int | None, + expected: list[int], ) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, -4, 5]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, -4, 5]})) result = df.select(result=nw.col("a").clip(lower_bound=lower, upper_bound=upper)) assert_equal_data(result, {"result": expected}) -def test_clip_expr_expressified(constructor: Constructor) -> None: +def test_clip_expr_expressified(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 2, 3, -4, 5], "lb": [3, 2, 1, 1, 1], "ub": [4, 4, 2, 2, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").clip("lb", nw.col("ub") + 1)) expected_dict = {"a": [3, 2, 3, 1, 3]} assert_equal_data(result, expected_dict) @@ -44,26 +47,26 @@ def test_clip_expr_expressified(constructor: Constructor) -> None: ], ) def test_clip_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, lower: int | None, upper: int | None, expected: list[int], ) -> None: - df = nw.from_native(constructor_eager({"a": [1, 2, 3, -4, 5]}), eager_only=True) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, -4, 5]}), eager_only=True) result = {"result": df["a"].clip(lower_bound=lower, upper_bound=upper)} assert_equal_data(result, {"result": expected}) -def test_clip_series_expressified(constructor_eager: ConstructorEager) -> None: +def test_clip_series_expressified(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3, -4, 5], "lb": [3, 2, 1, 1, 1], "ub": [4, 4, 2, 2, 2]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].clip(df["lb"], df["ub"] + 1).to_frame() expected_dict = {"a": [3, 2, 3, 1, 3]} assert_equal_data(result, expected_dict) -def test_clip_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_clip_invalid(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(nw.col("a").clip(nw.all(), nw.col("a", "b"))) diff --git a/tests/expr_and_series/coalesce_test.py b/tests/expr_and_series/coalesce_test.py index 5311b39c85..24ce42bd50 100644 --- a/tests/expr_and_series/coalesce_test.py +++ b/tests/expr_and_series/coalesce_test.py @@ -6,13 +6,13 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_coalesce_numeric(constructor: Constructor) -> None: +def test_coalesce_numeric(nw_frame_constructor: Constructor) -> None: data = { "a": [0, None, None, None, None], "b": [1, None, None, 5, 3], "c": [5, None, 3, 2, 1], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( no_lit=nw.coalesce("a", "b", "c"), @@ -22,13 +22,13 @@ def test_coalesce_numeric(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_coalesce_strings(constructor: Constructor) -> None: +def test_coalesce_strings(nw_frame_constructor: Constructor) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( no_lit=nw.coalesce("a", "b", "c"), @@ -41,41 +41,41 @@ def test_coalesce_strings(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_coalesce_series(constructor_eager: ConstructorEager) -> None: +def test_coalesce_series(nw_eager_constructor: ConstructorEager) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(result=nw.coalesce("a", "b", df["c"])) expected = {"result": ["0", None, "3", "5", "3"]} assert_equal_data(result, expected) -def test_coalesce_raises_non_expr(constructor: Constructor) -> None: +def test_coalesce_raises_non_expr(nw_frame_constructor: Constructor) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(TypeError, match="All arguments to `coalesce` must be of type"): df.select(implicit_lit=nw.coalesce("a", "b", "c", 10)) def test_coalesce_multi_output( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3277 - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # Dask infers the type to be `string` :shrug: # https://github.com/narwhals-dev/narwhals/issues/3279 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "col1": [True, None, False, False, None], "col2": [True, False, True, False, None], diff --git a/tests/expr_and_series/concat_str_test.py b/tests/expr_and_series/concat_str_test.py index 91e359c8fb..4ca1940137 100644 --- a/tests/expr_and_series/concat_str_test.py +++ b/tests/expr_and_series/concat_str_test.py @@ -21,16 +21,16 @@ ], ) def test_concat_str( - constructor: Constructor, + nw_frame_constructor: Constructor, *, ignore_nulls: bool, expected: list[str], request: pytest.FixtureRequest, ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): # nth only available after 1.0 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select( "a", @@ -61,8 +61,8 @@ def test_concat_str( assert_equal_data(result, {"a": expected}) -def test_concat_str_with_lit(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": ["cat", "dog", "pig"]})) +def test_concat_str_with_lit(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": ["cat", "dog", "pig"]})) result = df.with_columns(b=nw.concat_str("a", nw.lit("ab"))) expected = {"a": ["cat", "dog", "pig"], "b": ["catab", "dogab", "pigab"]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/corr_test.py b/tests/expr_and_series/corr_test.py index 15e371d62d..572a6d908f 100644 --- a/tests/expr_and_series/corr_test.py +++ b/tests/expr_and_series/corr_test.py @@ -20,18 +20,18 @@ ], ) def test_corr_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, output_name: str, a: str | nw.Expr, b: str | nw.Expr, expected_corr: float | None, ) -> None: - if "pyspark" in str(constructor) and expected_corr is None: + if "pyspark" in str(nw_frame_constructor) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.corr(a, b).round(2)) expected = {output_name: [expected_corr]} assert_equal_data(result, expected) @@ -47,7 +47,7 @@ def test_corr_expr( ], ) def test_corr_expr_spearman( - constructor: Constructor, + nw_frame_constructor: Constructor, output_name: str, a: str | nw.Expr, b: str | nw.Expr, @@ -55,10 +55,12 @@ def test_corr_expr_spearman( ) -> None: context = ( does_not_raise() - if any(x in str(constructor) for x in ("pandas", "polars", "modin", "cudf")) + if any( + x in str(nw_frame_constructor) for x in ("pandas", "polars", "modin", "cudf") + ) else pytest.raises(NotImplementedError) ) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with context: result = df.select(nw.corr(a, b, method="spearman").round(2)) expected = {output_name: [expected_corr]} @@ -70,18 +72,18 @@ def test_corr_expr_spearman( [("a", "a", "b", 0.87), ("a", "a", "c", None)], ) def test_corr_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, output_name: str, a: str, b: str, expected_corr: float | None, ) -> None: - if "pyspark" in str(constructor_eager) and expected_corr is None: + if "pyspark" in str(nw_eager_constructor) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.corr(df[a], df[b]).round(2)) expected = {output_name: [expected_corr]} assert_equal_data(result, expected) @@ -92,26 +94,26 @@ def test_corr_series( [("a", "a", "b", 0.87), ("a", "a", "c", None)], ) def test_corr_series_spearman( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, output_name: str, a: str, b: str, expected_corr: float | None, ) -> None: - if "pyspark" in str(constructor_eager) and expected_corr is None: + if "pyspark" in str(nw_eager_constructor) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) context = ( does_not_raise() if any( - x in str(constructor_eager) + x in str(nw_eager_constructor) for x in ("pandas", "polars", "modin", "cudf", "pyarrow") ) else pytest.raises(NotImplementedError) ) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) with context: result = df.select(nw.corr(df[a], df[b]).round(2)) expected = {output_name: [expected_corr]} diff --git a/tests/expr_and_series/cos_test.py b/tests/expr_and_series/cos_test.py index 4aa936d9bf..93a04bff4a 100644 --- a/tests/expr_and_series/cos_test.py +++ b/tests/expr_and_series/cos_test.py @@ -23,15 +23,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_cos_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_cos_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").cos()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_cos_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_cos_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.cos() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/count_test.py b/tests/expr_and_series/count_test.py index c3f34ee132..015258fe88 100644 --- a/tests/expr_and_series/count_test.py +++ b/tests/expr_and_series/count_test.py @@ -4,17 +4,17 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_count(constructor: Constructor) -> None: +def test_count(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, None, 6], "z": [7.0, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b", "z").count()) expected = {"a": [3], "b": [2], "z": [1]} assert_equal_data(result, expected) -def test_count_series(constructor_eager: ConstructorEager) -> None: +def test_count_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, None, 6], "z": [7.0, None, None]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"a": [df["a"].count()], "b": [df["b"].count()], "z": [df["z"].count()]} expected = {"a": [3], "b": [2], "z": [1]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/cum_count_test.py b/tests/expr_and_series/cum_count_test.py index f25c27f1c3..de725ddbc6 100644 --- a/tests/expr_and_series/cum_count_test.py +++ b/tests/expr_and_series/cum_count_test.py @@ -17,16 +17,16 @@ @pytest.mark.parametrize("reverse", [True, False]) -def test_cum_count_expr(constructor_eager: ConstructorEager, *, reverse: bool) -> None: +def test_cum_count_expr(nw_eager_constructor: ConstructorEager, *, reverse: bool) -> None: name = "reverse_cum_count" if reverse else "cum_count" - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").cum_count(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) -def test_cum_count_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_cum_count_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( cum_count=df["a"].cum_count(), reverse_cum_count=df["a"].cum_count(reverse=True) ) @@ -38,30 +38,30 @@ def test_cum_count_series(constructor_eager: ConstructorEager) -> None: ("reverse", "expected_a"), [(False, [1, 1, 2]), (True, [1, 2, 1])] ) def test_lazy_cum_count_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "arg entina": [None, 2, 3], "ban gkok": [1, 0, 2], diff --git a/tests/expr_and_series/cum_max_test.py b/tests/expr_and_series/cum_max_test.py index 82cf5ba179..d9279d5fef 100644 --- a/tests/expr_and_series/cum_max_test.py +++ b/tests/expr_and_series/cum_max_test.py @@ -19,13 +19,16 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_max_expr( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool + request: pytest.FixtureRequest, + nw_eager_constructor: ConstructorEager, + *, + reverse: bool, ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) name = "reverse_cum_max" if reverse else "cum_max" - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").cum_max(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -35,30 +38,32 @@ def test_cum_max_expr( ("reverse", "expected_a"), [(False, [2, 2, 3]), (True, [3, 3, 3])] ) def test_lazy_cum_max_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor({"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]}) + nw_frame_constructor( + {"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]} + ) ) result = df.with_columns( nw.col("a").cum_max(reverse=reverse).over("g", order_by="b") @@ -72,30 +77,30 @@ def test_lazy_cum_max_grouped( [(False, [4, 4, 4, 4, 4, 4, 4]), (True, [3, 3, 3, 3, 2, 3, 4])], ) def test_lazy_cum_max_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 2, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -120,24 +125,24 @@ def test_lazy_cum_max_ordered_by_nulls( ("reverse", "expected_a"), [(False, [2, 2, 3]), (True, [3, 3, 3])] ) def test_lazy_cum_max_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor) and reverse: + if "dask" in str(nw_frame_constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) + nw_frame_constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) ).sort("i") result = df.with_columns( nw.col("a").cum_max(reverse=reverse).over(order_by="b") @@ -151,24 +156,24 @@ def test_lazy_cum_max_ungrouped( [(False, [4, None, 4, 4, 4, 4, 4]), (True, [3, None, 3, 3, 2, 3, 4])], ) def test_lazy_cum_max_ungrouped_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, None, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -188,12 +193,12 @@ def test_lazy_cum_max_ungrouped_ordered_by_nulls( def test_cum_max_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( cum_max=df["a"].cum_max(), reverse_cum_max=df["a"].cum_max(reverse=True) ) diff --git a/tests/expr_and_series/cum_min_test.py b/tests/expr_and_series/cum_min_test.py index 43fc1f5b81..fde996e161 100644 --- a/tests/expr_and_series/cum_min_test.py +++ b/tests/expr_and_series/cum_min_test.py @@ -21,13 +21,16 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_min_expr( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool + request: pytest.FixtureRequest, + nw_eager_constructor: ConstructorEager, + *, + reverse: bool, ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) name = "reverse_cum_min" if reverse else "cum_min" - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").cum_min(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -37,30 +40,32 @@ def test_cum_min_expr( ("reverse", "expected_a"), [(False, [1, 2, 1]), (True, [1, 1, 3])] ) def test_lazy_cum_min_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor({"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]}) + nw_frame_constructor( + {"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]} + ) ) result = df.with_columns( nw.col("a").cum_min(reverse=reverse).over("g", order_by="b") @@ -74,36 +79,40 @@ def test_lazy_cum_min_grouped( [(False, [1, 2, 1, None, 1, 2, 4]), (True, [1, 1, 2, None, 2, 1, 1])], ) def test_lazy_cum_min_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "pandas_nullable" in str(constructor): + if "pandas_nullable" in str(nw_frame_constructor): # https://github.com/pandas-dev/pandas/issues/62473 request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pyarrow" in str(constructor) and is_windows() and PYARROW_VERSION < (22, 0): + if ( + "pyarrow" in str(nw_frame_constructor) + and is_windows() + and PYARROW_VERSION < (22, 0) + ): # https://github.com/pandas-dev/pandas/issues/62477 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 2, 3, None, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -128,23 +137,23 @@ def test_lazy_cum_min_ordered_by_nulls( ("reverse", "expected_a"), [(False, [1, 2, 1]), (True, [1, 1, 3])] ) def test_lazy_cum_min_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor) and reverse: + if "dask" in str(nw_frame_constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) + nw_frame_constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) ).sort("i") result = df.with_columns( nw.col("a").cum_min(reverse=reverse).over(order_by="b") @@ -158,23 +167,23 @@ def test_lazy_cum_min_ungrouped( [(False, [1, 2, 1, 1, 1, 2, 4]), (True, [1, 1, 2, 1, 2, 1, 1])], ) def test_lazy_cum_min_ungrouped_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 2, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -194,12 +203,12 @@ def test_lazy_cum_min_ungrouped_ordered_by_nulls( def test_cum_min_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( cum_min=df["a"].cum_min(), reverse_cum_min=df["a"].cum_min(reverse=True) ) diff --git a/tests/expr_and_series/cum_prod_test.py b/tests/expr_and_series/cum_prod_test.py index 778c48bc67..07d7b0b362 100644 --- a/tests/expr_and_series/cum_prod_test.py +++ b/tests/expr_and_series/cum_prod_test.py @@ -19,25 +19,28 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_prod_expr( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool + request: pytest.FixtureRequest, + nw_eager_constructor: ConstructorEager, + *, + reverse: bool, ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) name = "reverse_cum_prod" if reverse else "cum_prod" - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").cum_prod(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) def test_cum_prod_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( cum_prod=df["a"].cum_prod(), reverse_cum_prod=df["a"].cum_prod(reverse=True) ) @@ -48,33 +51,33 @@ def test_cum_prod_series( ("reverse", "expected_a"), [(False, [2, 2, 6, None]), (True, [3, 6, 3, None])] ) def test_lazy_cum_prod_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="probably bugged") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): # https://github.com/ibis-project/ibis/issues/10542 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "arg entina": [1, 2, 3, None], "ban gkok": [1, 0, 2, 3], diff --git a/tests/expr_and_series/cum_sum_test.py b/tests/expr_and_series/cum_sum_test.py index f3f0f780db..243868a585 100644 --- a/tests/expr_and_series/cum_sum_test.py +++ b/tests/expr_and_series/cum_sum_test.py @@ -18,9 +18,9 @@ @pytest.mark.parametrize("reverse", [True, False]) -def test_cum_sum_expr(constructor_eager: ConstructorEager, *, reverse: bool) -> None: +def test_cum_sum_expr(nw_eager_constructor: ConstructorEager, *, reverse: bool) -> None: name = "reverse_cum_sum" if reverse else "cum_sum" - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("arg entina").cum_sum(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -30,28 +30,28 @@ def test_cum_sum_expr(constructor_eager: ConstructorEager, *, reverse: bool) -> ("reverse", "expected_a"), [(False, [3, 2, 6]), (True, [4, 6, 3])] ) def test_lazy_cum_sum_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "arg entina": [1, 2, 3], "ban gkok": [1, 0, 2], @@ -77,34 +77,38 @@ def test_lazy_cum_sum_grouped( [(False, [None, 6, 13, 10, 15, 9, 4]), (True, [None, 11, 5, 6, 2, 9, 15])], ) def test_lazy_cum_sum_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(constructor): + if "pyarrow_table" in str(nw_frame_constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "pandas_nullable" in str(constructor) and not reverse: + if "pandas_nullable" in str(nw_frame_constructor) and not reverse: # https://github.com/pandas-dev/pandas/issues/62473 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pyarrow" in str(constructor) and is_windows() and PYARROW_VERSION < (22, 0): + if ( + "pyarrow" in str(nw_frame_constructor) + and is_windows() + and PYARROW_VERSION < (22, 0) + ): # https://github.com/pandas-dev/pandas/issues/62477 request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor( + nw_frame_constructor( { "arg entina": [None, 2, 3, 1, 2, 3, 4], "ban gkok": [1, -1, 3, 2, 5, 0, None], @@ -129,22 +133,24 @@ def test_lazy_cum_sum_ordered_by_nulls( ("reverse", "expected_a"), [(False, [3, 2, 6]), (True, [4, 6, 3])] ) def test_lazy_cum_sum_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor) and reverse: + if "dask" in str(nw_frame_constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor({"arg entina": [2, 3, 1], "ban gkok": [0, 2, 1], "i ran": [1, 2, 0]}) + nw_frame_constructor( + {"arg entina": [2, 3, 1], "ban gkok": [0, 2, 1], "i ran": [1, 2, 0]} + ) ).sort("i ran") result = df.with_columns( nw.col("arg entina").cum_sum(reverse=reverse).over(order_by="ban gkok") @@ -158,22 +164,22 @@ def test_lazy_cum_sum_ungrouped( [(False, [10, 6, 14, 11, 16, 9, 4]), (True, [7, 12, 5, 6, 2, 10, 16])], ) def test_lazy_cum_sum_ungrouped_ordered_by_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - constructor( + nw_frame_constructor( { "arg entina": [1, 2, 3, 1, 2, 3, 4], "ban gkok": [1, -1, 3, 2, 5, 0, None], @@ -192,8 +198,8 @@ def test_lazy_cum_sum_ungrouped_ordered_by_nulls( assert_equal_data(result, expected) -def test_cum_sum_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_cum_sum_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( cum_sum=df["arg entina"].cum_sum(), reverse_cum_sum=df["arg entina"].cum_sum(reverse=True), @@ -201,11 +207,11 @@ def test_cum_sum_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_shift_cum_sum(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): +def test_shift_cum_sum(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() data = {"arg entina": [1, 2, 3, 4, 5], "i": list(range(5))} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.with_columns(kalimantan=nw.col("arg entina").shift(1).cum_sum()) expected = { "arg entina": [1, 2, 3, 4, 5], diff --git a/tests/expr_and_series/diff_test.py b/tests/expr_and_series/diff_test.py index dc7440541e..0c25a92243 100644 --- a/tests/expr_and_series/diff_test.py +++ b/tests/expr_and_series/diff_test.py @@ -14,8 +14,8 @@ data = {"i": [0, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1]} -def test_diff(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_diff(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.with_columns(c_diff=nw.col("c").diff()).filter(nw.col("i") > 0) expected = { "i": [1, 2, 3, 4], @@ -26,13 +26,13 @@ def test_diff(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_diff_lazy(constructor: Constructor) -> None: +def test_diff_lazy(nw_frame_constructor: Constructor) -> None: data = {"i": [None, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1]} - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(c_diff=nw.col("c").diff().over(order_by="i")).filter( ~nw.col("i").is_null() ) @@ -46,19 +46,19 @@ def test_diff_lazy(constructor: Constructor) -> None: def test_diff_lazy_grouped( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): # https://github.com/dask/dask/issues/11806 # https://github.com/rapidsai/cudf/issues/18160 # wooah their issue numbers use exactly the same digits but in a different order request.applymarker(pytest.mark.xfail) data = {"i": [0, 1, 2, 3, 4], "b": [1, 1, 1, 2, 2], "c": [5, 4, 3, 2, 1]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns(c_diff=nw.col("c").diff().over("b", order_by="i")) .filter(nw.col("i") > 0) @@ -73,8 +73,8 @@ def test_diff_lazy_grouped( assert_equal_data(result, expected) -def test_diff_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_diff_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = { "i": [1, 2, 3, 4], "b": [2, 3, 5, 3], diff --git a/tests/expr_and_series/division_by_zero_test.py b/tests/expr_and_series/division_by_zero_test.py index 6e8313b522..1f4e81473f 100644 --- a/tests/expr_and_series/division_by_zero_test.py +++ b/tests/expr_and_series/division_by_zero_test.py @@ -19,10 +19,10 @@ @pytest.mark.parametrize("get_denominator", [lambda _: 0, lambda df: df["denominator"]]) def test_series_truediv_by_zero( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, get_denominator: Callable[[nw.DataFrame[Any]], int | nw.Series[Any]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) denominator = get_denominator(df) result = {"int": df["int"] / denominator, "float": df["float"] / denominator} expected = {"int": expected_truediv, "float": expected_truediv} @@ -31,9 +31,9 @@ def test_series_truediv_by_zero( @pytest.mark.parametrize("denominator", [0, nw.lit(0), nw.col("denominator")]) def test_expr_truediv_by_zero( - constructor: Constructor, denominator: int | nw.Expr + nw_frame_constructor: Constructor, denominator: int | nw.Expr ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("int", "float") / denominator) expected = {"int": expected_truediv, "float": expected_truediv} assert_equal_data(result, expected) @@ -41,13 +41,13 @@ def test_expr_truediv_by_zero( @pytest.mark.parametrize("get_denominator", [lambda _: 0, lambda df: df["denominator"]]) def test_series_floordiv_by_zero( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, get_denominator: Callable[[nw.DataFrame[Any]], int | nw.Series[Any]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) - if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if df.implementation.is_pandas_like(): request.applymarker(pytest.mark.xfail) @@ -60,11 +60,13 @@ def test_series_floordiv_by_zero( @pytest.mark.parametrize("denominator", [0, nw.lit(0), nw.col("denominator")]) def test_expr_floordiv_by_zero( - constructor: Constructor, request: pytest.FixtureRequest, denominator: int | nw.Expr + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + denominator: int | nw.Expr, ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if df.implementation.is_pandas_like(): request.applymarker(pytest.mark.xfail) @@ -82,9 +84,9 @@ def test_expr_floordiv_by_zero( ), ) def test_series_rtruediv_by_zero( - constructor_eager: ConstructorEager, numerator: float, expected: float + nw_eager_constructor: ConstructorEager, numerator: float, expected: float ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"result": numerator / df["denominator"]} assert_equal_data(result, {"result": [expected] * len(df)}) @@ -96,9 +98,9 @@ def test_series_rtruediv_by_zero( ), ) def test_expr_rtruediv_by_zero( - constructor: Constructor, numerator: float, expected: float + nw_frame_constructor: Constructor, numerator: float, expected: float ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(result=numerator / nw.col("denominator")) assert_equal_data(result, {"result": [expected] * len(data["denominator"])}) assert_equal_data(result.select((~nw.all().is_finite()).all()), {"result": [True]}) @@ -106,22 +108,25 @@ def test_expr_rtruediv_by_zero( @pytest.mark.parametrize("numerator", data["int"]) def test_series_rfloordiv_by_zero( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest, numerator: float + nw_eager_constructor: ConstructorEager, + request: pytest.FixtureRequest, + numerator: float, ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if any( - x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") + x in str(nw_eager_constructor) + for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") ) or ( any( - x in str(constructor_eager) + x in str(nw_eager_constructor) for x in ("pandas_nullable", "pandas_constructor", "modin_constructor") ) and numerator != 0 ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"result": numerator // df["denominator"]} assert_equal_data(result, {"result": expected_floordiv}) @@ -129,22 +134,23 @@ def test_series_rfloordiv_by_zero( @pytest.mark.parametrize("numerator", data["int"]) def test_expr_rfloordiv_by_zero( - constructor: Constructor, request: pytest.FixtureRequest, numerator: float + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, numerator: float ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if any( - x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") + x in str(nw_frame_constructor) + for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") ) or ( any( - x in str(constructor) + x in str(nw_frame_constructor) for x in ("pandas_nullable", "pandas_constructor", "modin_constructor") ) and numerator != 0 ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(result=numerator // nw.col("denominator")) expected = {"result": expected_floordiv} diff --git a/tests/expr_and_series/double_selected_test.py b/tests/expr_and_series/double_selected_test.py index 48b76222ec..72dd6314e4 100644 --- a/tests/expr_and_series/double_selected_test.py +++ b/tests/expr_and_series/double_selected_test.py @@ -7,9 +7,9 @@ from tests.utils import Constructor, assert_equal_data -def test_double_selected(constructor: Constructor) -> None: +def test_double_selected(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7, 8, 9]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b") * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12]} diff --git a/tests/expr_and_series/double_test.py b/tests/expr_and_series/double_test.py index de6a1afb09..517d1c351e 100644 --- a/tests/expr_and_series/double_test.py +++ b/tests/expr_and_series/double_test.py @@ -4,17 +4,17 @@ from tests.utils import Constructor, assert_equal_data -def test_double(constructor: Constructor) -> None: +def test_double(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0]} assert_equal_data(result, expected) -def test_double_alias(constructor: Constructor) -> None: +def test_double_alias(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a").alias("o"), nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0], "o": [1, 3, 2]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/drop_nulls_test.py b/tests/expr_and_series/drop_nulls_test.py index d067552eb6..f8e663d694 100644 --- a/tests/expr_and_series/drop_nulls_test.py +++ b/tests/expr_and_series/drop_nulls_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_drop_nulls(constructor_eager: ConstructorEager) -> None: +def test_drop_nulls(nw_eager_constructor: ConstructorEager) -> None: data = { "A": [1, 2, None, 4], "B": [5, 6, 7, 8], @@ -14,7 +14,7 @@ def test_drop_nulls(constructor_eager: ConstructorEager) -> None: "D": [9, 10, 11, 12], } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result_a = df.select(nw.col("A").drop_nulls()) result_b = df.select(nw.col("B").drop_nulls()) @@ -31,8 +31,10 @@ def test_drop_nulls(constructor_eager: ConstructorEager) -> None: assert_equal_data(result_d, expected_d) -def test_drop_nulls_agg(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): +def test_drop_nulls_agg( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) data = { "A": [1, 2, None, 4], @@ -41,13 +43,13 @@ def test_drop_nulls_agg(constructor: Constructor, request: pytest.FixtureRequest "D": [9, 10, 11, 12], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.all().drop_nulls().len()) expected = {"A": [3], "B": [4], "C": [0], "D": [4]} assert_equal_data(result, expected) -def test_drop_nulls_series(constructor_eager: ConstructorEager) -> None: +def test_drop_nulls_series(nw_eager_constructor: ConstructorEager) -> None: data = { "A": [1, 2, None, 4], "B": [5, 6, 7, 8], @@ -55,7 +57,7 @@ def test_drop_nulls_series(constructor_eager: ConstructorEager) -> None: "D": [9, 10, 11, 12], } - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_a = df.select(df["A"].drop_nulls()) result_b = df.select(df["B"].drop_nulls()) diff --git a/tests/expr_and_series/dt/convert_time_zone_test.py b/tests/expr_and_series/dt/convert_time_zone_test.py index 8fd654ad6d..d9074f89f0 100644 --- a/tests/expr_and_series/dt/convert_time_zone_test.py +++ b/tests/expr_and_series/dt/convert_time_zone_test.py @@ -21,16 +21,16 @@ def test_convert_time_zone( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pyarrow_table" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -38,7 +38,7 @@ def test_convert_time_zone( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.convert_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -50,16 +50,16 @@ def test_convert_time_zone( def test_convert_time_zone_series( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(constructor_eager) and is_windows()) - or ("pyarrow_table" in str(constructor_eager) and is_windows()) - or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(nw_eager_constructor) and is_windows()) + or ("pyarrow_table" in str(nw_eager_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(constructor_eager) for x in ("cudf",)): + if any(x in str(nw_eager_constructor) for x in ("cudf",)): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -67,7 +67,7 @@ def test_convert_time_zone_series( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.convert_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -79,18 +79,18 @@ def test_convert_time_zone_series( def test_convert_time_zone_from_none( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pyarrow_table" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): # polars used to disallow this pytest.skip() data = { @@ -99,7 +99,7 @@ def test_convert_time_zone_from_none( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").dt.replace_time_zone(None).dt.convert_time_zone("Asia/Kathmandu") ) @@ -112,26 +112,26 @@ def test_convert_time_zone_from_none( assert_equal_data(result_str, expected) -def test_convert_time_zone_to_none(constructor: Constructor) -> None: +def test_convert_time_zone_to_none(nw_frame_constructor: Constructor) -> None: data = { "a": [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(TypeError, match="Target `time_zone` cannot be `None`"): df.select(nw.col("a").dt.convert_time_zone(None)) # type: ignore[arg-type] -def test_convert_time_zone_to_none_series(constructor_eager: ConstructorEager) -> None: +def test_convert_time_zone_to_none_series(nw_eager_constructor: ConstructorEager) -> None: data = { "a": [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) with pytest.raises(TypeError, match="Target `time_zone` cannot be `None`"): df["a"].dt.convert_time_zone(None) # type: ignore[arg-type] diff --git a/tests/expr_and_series/dt/datetime_attributes_test.py b/tests/expr_and_series/dt/datetime_attributes_test.py index c7bf55e7c0..cc6f867db4 100644 --- a/tests/expr_and_series/dt/datetime_attributes_test.py +++ b/tests/expr_and_series/dt/datetime_attributes_test.py @@ -35,22 +35,22 @@ ) def test_datetime_attributes( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, attribute: str, expected: list[int], ) -> None: if ( attribute == "date" - and "pandas" in str(constructor) - and "pyarrow" not in str(constructor) + and "pandas" in str(nw_frame_constructor) + and "pyarrow" not in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) - if attribute == "date" and "cudf" in str(constructor): + if attribute == "date" and "cudf" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if attribute == "nanosecond" and "ibis" in str(constructor): + if attribute == "nanosecond" and "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a").dt, attribute)()) assert_equal_data(result, {"a": expected}) @@ -74,35 +74,39 @@ def test_datetime_attributes( ) def test_datetime_attributes_series( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, attribute: str, expected: list[int], ) -> None: if ( attribute == "date" - and "pandas" in str(constructor_eager) - and "pyarrow" not in str(constructor_eager) + and "pandas" in str(nw_eager_constructor) + and "pyarrow" not in str(nw_eager_constructor) ): request.applymarker(pytest.mark.xfail) - if attribute == "date" and "cudf" in str(constructor_eager): + if attribute == "date" and "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(getattr(df["a"].dt, attribute)()) assert_equal_data(result, {"a": expected}) def test_datetime_chained_attributes( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pandas" in str(constructor_eager) and "pyarrow" not in str(constructor_eager): + if "pandas" in str(nw_eager_constructor) and "pyarrow" not in str( + nw_eager_constructor + ): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor_eager) and "pyarrow" not in str(constructor_eager): + if "modin" in str(nw_eager_constructor) and "pyarrow" not in str( + nw_eager_constructor + ): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.date().dt.year()) assert_equal_data(result, {"a": [2021, 2020]}) @@ -110,9 +114,11 @@ def test_datetime_chained_attributes( assert_equal_data(result, {"a": [2021, 2020]}) -def test_to_date(request: pytest.FixtureRequest, constructor: Constructor) -> None: +def test_to_date( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: if any( - x in str(constructor) + x in str(nw_frame_constructor) for x in ( "pandas_constructor", "pandas_nullable_constructor", @@ -122,11 +128,11 @@ def test_to_date(request: pytest.FixtureRequest, constructor: Constructor) -> No ): request.applymarker(pytest.mark.xfail) dates = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - if "dask" in str(constructor): - df_dask = cast("dd.DataFrame", constructor(dates)) + if "dask" in str(nw_frame_constructor): + df_dask = cast("dd.DataFrame", nw_frame_constructor(dates)) df_dask = cast("dd.DataFrame", df_dask.astype({"a": "timestamp[ns][pyarrow]"})) df = nw.from_native(df_dask) else: - df = nw.from_native(constructor(dates)) + df = nw.from_native(nw_frame_constructor(dates)) result = df.select(nw.col("a").dt.date()) assert result.collect_schema() == {"a": nw.Date} diff --git a/tests/expr_and_series/dt/datetime_duration_test.py b/tests/expr_and_series/dt/datetime_duration_test.py index b84ecfa66e..2f1dfeaa59 100644 --- a/tests/expr_and_series/dt/datetime_duration_test.py +++ b/tests/expr_and_series/dt/datetime_duration_test.py @@ -26,19 +26,19 @@ ) def test_duration_attributes( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, attribute: str, expected_a: list[int], expected_b: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_frame_constructor): pytest.skip() - if "pyspark" in str(constructor) or "ibis" in str(constructor): + if "pyspark" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and attribute == "total_nanoseconds": + if "duckdb" in str(nw_frame_constructor) and attribute == "total_nanoseconds": request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_a = df.select(getattr(nw.col("a").dt, attribute)().fill_null(0)) assert_equal_data(result_a, {"a": expected_a}) @@ -59,22 +59,22 @@ def test_duration_attributes( ) def test_duration_attributes_nano( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, attribute: str, expected_c: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_frame_constructor): pytest.skip() - if "pyspark" in str(constructor) or "ibis" in str(constructor): + if "pyspark" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and attribute == "total_nanoseconds": + if "duckdb" in str(nw_frame_constructor) and attribute == "total_nanoseconds": request.applymarker(pytest.mark.xfail) pytest.importorskip("numpy") import numpy as np data = {"c": np.array([None, 20], dtype="timedelta64[ns]")} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_c = df.select(getattr(nw.col("c").dt, attribute)().fill_null(0)) assert_equal_data(result_c, {"c": expected_c}) @@ -92,15 +92,15 @@ def test_duration_attributes_nano( ) def test_duration_attributes_series( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, attribute: str, expected_a: list[int], expected_b: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor_eager): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_a = df.select(getattr(df["a"].dt, attribute)().fill_null(0)) assert_equal_data(result_a, {"a": expected_a}) @@ -121,18 +121,18 @@ def test_duration_attributes_series( ) def test_duration_attributes_series_nano( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, attribute: str, expected_c: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor_eager): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) pytest.importorskip("numpy") import numpy as np data = {"c": np.array([None, 20], dtype="timedelta64[ns]")} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_c = df.select(getattr(df["c"].dt, attribute)().fill_null(0)) assert_equal_data(result_c, {"c": expected_c}) diff --git a/tests/expr_and_series/dt/offset_by_test.py b/tests/expr_and_series/dt/offset_by_test.py index 9085edb185..55888dbd67 100644 --- a/tests/expr_and_series/dt/offset_by_test.py +++ b/tests/expr_and_series/dt/offset_by_test.py @@ -135,24 +135,25 @@ ) def test_offset_by( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, by: str, expected: list[datetime], ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() if any(x in by for x in ("y", "q", "mo")) and any( - x in str(constructor) for x in ("dask", "pyarrow", "ibis") + x in str(nw_frame_constructor) for x in ("dask", "pyarrow", "ibis") ): request.applymarker(pytest.mark.xfail()) if "ns" in by and any( - x in str(constructor) for x in ("dask", "pyspark", "ibis", "cudf", "duckdb") + x in str(nw_frame_constructor) + for x in ("dask", "pyspark", "ibis", "cudf", "duckdb") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(constructor) for x in ("dask", "ibis")): + if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask", "ibis")): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": expected}) @@ -167,26 +168,31 @@ def test_offset_by( ], ) def test_offset_by_tz( - request: pytest.FixtureRequest, constructor: Constructor, by: str, expected: str + request: pytest.FixtureRequest, + nw_frame_constructor: Constructor, + by: str, + expected: str, ) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pyarrow_table" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(constructor) for x in ("duckdb", "pyspark", "sqlframe", "ibis")): + if any( + x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "sqlframe", "ibis") + ): # pyspark,duckdb don't support changing time zones. # convert_time_zone is not supported for ibis. request.applymarker(pytest.mark.xfail()) if any(x in by for x in ("y", "q", "mo")) and any( - x in str(constructor) for x in ("dask", "pyarrow", "ibis") + x in str(nw_frame_constructor) for x in ("dask", "pyarrow", "ibis") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(constructor) for x in ("dask",)): + if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask",)): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(constructor(data_tz)) + df = nw.from_native(nw_frame_constructor(data_tz)) df = df.select(nw.col("a").dt.convert_time_zone("Asia/Kathmandu")) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": [datetime.strptime(expected, "%Y-%m-%dT%H:%M%z")]}) @@ -201,36 +207,41 @@ def test_offset_by_tz( ], ) def test_offset_by_dst( - request: pytest.FixtureRequest, constructor: Constructor, by: str, expected: str + request: pytest.FixtureRequest, + nw_frame_constructor: Constructor, + by: str, + expected: str, ) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pyarrow_table" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(constructor) for x in ("duckdb", "sqlframe", "pyspark", "ibis")): + if any( + x in str(nw_frame_constructor) for x in ("duckdb", "sqlframe", "pyspark", "ibis") + ): # pyspark,duckdb don't support changing time zones. # convert_time_zone is not supported for ibis. request.applymarker(pytest.mark.xfail()) - if any(x in str(constructor) for x in ("cudf",)) and "d" not in by: + if any(x in str(nw_frame_constructor) for x in ("cudf",)) and "d" not in by: # cudf: https://github.com/rapidsai/cudf/issues/19363 request.applymarker(pytest.mark.xfail()) if any(x in by for x in ("y", "q", "mo")) and any( - x in str(constructor) for x in ("dask", "pyarrow") + x in str(nw_frame_constructor) for x in ("dask", "pyarrow") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(constructor) for x in ("dask",)): + if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask",)): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(constructor(data_dst)) + df = nw.from_native(nw_frame_constructor(data_dst)) df = df.with_columns(a=nw.col("a").dt.convert_time_zone("Europe/Amsterdam")) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": [datetime.strptime(expected, "%Y-%m-%dT%H:%M%z")]}) -def test_offset_by_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_offset_by_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.offset_by("1h")) expected = { "a": [ @@ -241,10 +252,10 @@ def test_offset_by_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_offset_by_invalid_interval(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_offset_by_invalid_interval(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) msg = "Invalid `every` string" with pytest.raises(ValueError, match=msg): df.select(nw.col("a").dt.offset_by("1r")) @@ -266,12 +277,14 @@ def test_offset_by_date_pandas() -> None: assert_equal_data(result, expected) -def test_offset_by_3471(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if any(x in str(constructor) for x in ("dask", "ibis")): +def test_offset_by_3471( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if any(x in str(nw_frame_constructor) for x in ("dask", "ibis")): request.applymarker(pytest.mark.xfail()) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - date_nw = nw.from_native(constructor({"date": [date(2026, 1, 31)]})) + date_nw = nw.from_native(nw_frame_constructor({"date": [date(2026, 1, 31)]})) existent_col_offset = nw.col("date").dt.offset_by("-1d") result = date_nw.with_columns(existent_col_offset) diff --git a/tests/expr_and_series/dt/replace_time_zone_test.py b/tests/expr_and_series/dt/replace_time_zone_test.py index 27bc394b69..ed8bddf5c1 100644 --- a/tests/expr_and_series/dt/replace_time_zone_test.py +++ b/tests/expr_and_series/dt/replace_time_zone_test.py @@ -15,16 +15,16 @@ def test_replace_time_zone( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() - if any(x in str(constructor) for x in ("cudf", "pyspark", "ibis", "duckdb")): + if any(x in str(nw_frame_constructor) for x in ("cudf", "pyspark", "ibis", "duckdb")): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -32,7 +32,7 @@ def test_replace_time_zone( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -43,11 +43,11 @@ def test_replace_time_zone( assert_equal_data(result_str, expected) -def test_replace_time_zone_none(constructor: Constructor) -> None: +def test_replace_time_zone_none(nw_frame_constructor: Constructor) -> None: if ( - ("pyarrow" in str(constructor) and is_windows()) - or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() data = { @@ -56,7 +56,7 @@ def test_replace_time_zone_none(constructor: Constructor) -> None: datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.replace_time_zone(None)) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -68,15 +68,15 @@ def test_replace_time_zone_none(constructor: Constructor) -> None: def test_replace_time_zone_series( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(constructor_eager) and is_windows()) - or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(nw_eager_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() - if any(x in str(constructor_eager) for x in ("cudf",)): + if any(x in str(nw_eager_constructor) for x in ("cudf",)): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -84,7 +84,7 @@ def test_replace_time_zone_series( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.replace_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -95,11 +95,11 @@ def test_replace_time_zone_series( assert_equal_data(result_str, expected) -def test_replace_time_zone_none_series(constructor_eager: ConstructorEager) -> None: +def test_replace_time_zone_none_series(nw_eager_constructor: ConstructorEager) -> None: if ( - ("pyarrow" in str(constructor_eager) and is_windows()) - or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(nw_eager_constructor) and is_windows()) + or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() data = { @@ -108,7 +108,7 @@ def test_replace_time_zone_none_series(constructor_eager: ConstructorEager) -> N datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.replace_time_zone(None)) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime diff --git a/tests/expr_and_series/dt/timestamp_test.py b/tests/expr_and_series/dt/timestamp_test.py index e199fcac76..f08c694a64 100644 --- a/tests/expr_and_series/dt/timestamp_test.py +++ b/tests/expr_and_series/dt/timestamp_test.py @@ -45,27 +45,27 @@ ) def test_timestamp_datetimes( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, original_time_unit: Literal["us", "ns", "ms", "s"], time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) - if original_time_unit == "s" and "polars" in str(constructor): + if original_time_unit == "s" and "polars" in str(nw_frame_constructor): pytest.skip("Second precision not supported in Polars") - if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < ( + if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < ( 2, 2, ): # pragma: no cover pytest.skip("Requires pandas >= 2.2 for reliable pyarrow-backed timestamps") datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - df = nw.from_native(constructor(datetimes)) + df = nw.from_native(nw_frame_constructor(datetimes)) dtype = nw.Datetime(time_unit_compat(original_time_unit, request)) result = df.select(nw.col("a").cast(dtype).dt.timestamp(time_unit)) assert_equal_data(result, {"a": expected}) @@ -90,32 +90,32 @@ def test_timestamp_datetimes( ) def test_timestamp_datetimes_tz_aware( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, original_time_unit: Literal["us", "ns", "ms", "s"], time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) version_conditions = [ ( - is_pyarrow_windows_no_tzdata(constructor), + is_pyarrow_windows_no_tzdata(nw_frame_constructor), "Timezone database is not installed on Windows", ), ( - "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,), + "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,), "Requires pandas >= 2.0 for pyarrow support", ), ( - "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 2), + "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 2), "Requires pandas >= 2.2 for reliable timestamps", ), ( - "dask" in str(constructor) and PANDAS_VERSION < (2, 1), + "dask" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1), "Requires pandas >= 2.1 for dask support", ), ] @@ -124,10 +124,10 @@ def test_timestamp_datetimes_tz_aware( if condition: pytest.skip(reason) # pragma: no cover - if original_time_unit == "s" and "polars" in str(constructor): + if original_time_unit == "s" and "polars" in str(nw_frame_constructor): pytest.skip() datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - df = nw.from_native(constructor(datetimes)) + df = nw.from_native(nw_frame_constructor(datetimes)) dtype = nw.Datetime(time_unit_compat(original_time_unit, request)) result = df.select( nw.col("a") @@ -149,13 +149,13 @@ def test_timestamp_datetimes_tz_aware( ) def test_timestamp_dates( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) @@ -165,30 +165,30 @@ def test_timestamp_dates( "cudf", "modin_constructor", ) - if any(x in str(constructor) for x in unsupported_backends): + if any(x in str(nw_frame_constructor) for x in unsupported_backends): pytest.skip("Backend does not support date type") dates = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): df = nw.from_native( - constructor(dates).astype({"a": "timestamp[ns][pyarrow]"}) # type: ignore[union-attr] + nw_frame_constructor(dates).astype({"a": "timestamp[ns][pyarrow]"}) # type: ignore[union-attr] ) else: - df = nw.from_native(constructor(dates)) + df = nw.from_native(nw_frame_constructor(dates)) result = df.select(nw.col("a").dt.date().dt.timestamp(time_unit)) assert_equal_data(result, {"a": expected}) def test_timestamp_invalid_date( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) - if "polars" in str(constructor): + if "polars" in str(nw_frame_constructor): request.applymarker( pytest.mark.xfail( reason="Invalid date handling not yet implemented in Polars" @@ -196,8 +196,8 @@ def test_timestamp_invalid_date( ) data_str = {"a": ["x", "y", None]} data_num = {"a": [1, 2, None]} - df_str = nw.from_native(constructor(data_str)) - df_num = nw.from_native(constructor(data_num)) + df_str = nw.from_native(nw_frame_constructor(data_str)) + df_num = nw.from_native(nw_frame_constructor(data_num)) msg = "Input should be either of Date or Datetime type" with pytest.raises(TypeError, match=msg): df_str.select(nw.col("a").dt.timestamp()) @@ -205,26 +205,26 @@ def test_timestamp_invalid_date( df_num.select(nw.col("a").dt.timestamp()) -def test_timestamp_invalid_unit_expr(constructor: Constructor) -> None: +def test_timestamp_invalid_unit_expr(nw_frame_constructor: Constructor) -> None: time_unit_invalid = "i" msg = ( "invalid `time_unit`" f"\n\nExpected one of {{'ns', 'us', 'ms'}}, got {time_unit_invalid!r}." ) with pytest.raises(ValueError, match=msg): - nw.from_native(constructor(data)).select( + nw.from_native(nw_frame_constructor(data)).select( nw.col("a").dt.timestamp(time_unit_invalid) # type: ignore[arg-type] ) -def test_timestamp_invalid_unit_series(constructor_eager: ConstructorEager) -> None: +def test_timestamp_invalid_unit_series(nw_eager_constructor: ConstructorEager) -> None: time_unit_invalid = "i" msg = ( "invalid `time_unit`" f"\n\nExpected one of {{'ns', 'us', 'ms'}}, got {time_unit_invalid!r}." ) with pytest.raises(ValueError, match=msg): - nw.from_native(constructor_eager(data))["a"].dt.timestamp(time_unit_invalid) # type: ignore[arg-type] + nw.from_native(nw_eager_constructor(data))["a"].dt.timestamp(time_unit_invalid) # type: ignore[arg-type] @given( diff --git a/tests/expr_and_series/dt/to_string_test.py b/tests/expr_and_series/dt/to_string_test.py index 4fd4c14c66..f9d6d210a1 100644 --- a/tests/expr_and_series/dt/to_string_test.py +++ b/tests/expr_and_series/dt/to_string_test.py @@ -17,8 +17,8 @@ "fmt", ["%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%G-W%V-%u", "%G-W%V"] ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") -def test_dt_to_string_series(constructor_eager: ConstructorEager, fmt: str) -> None: - input_frame = nw.from_native(constructor_eager(data), eager_only=True) +def test_dt_to_string_series(nw_eager_constructor: ConstructorEager, fmt: str) -> None: + input_frame = nw.from_native(nw_eager_constructor(data), eager_only=True) input_series = input_frame["a"] expected_col = [datetime.strftime(d, fmt) for d in data["a"]] @@ -26,7 +26,8 @@ def test_dt_to_string_series(constructor_eager: ConstructorEager, fmt: str) -> N result = {"a": input_series.dt.to_string(fmt)} if any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "pyarrow_table", "modin"] + x in str(nw_eager_constructor) + for x in ["pandas_pyarrow", "pyarrow_table", "modin"] ): # PyArrow differs from other libraries, in that %S also shows # the fraction of a second. @@ -39,13 +40,16 @@ def test_dt_to_string_series(constructor_eager: ConstructorEager, fmt: str) -> N "fmt", ["%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%G-W%V-%u", "%G-W%V"] ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") -def test_dt_to_string_expr(constructor: Constructor, fmt: str) -> None: - input_frame = nw.from_native(constructor(data)) +def test_dt_to_string_expr(nw_frame_constructor: Constructor, fmt: str) -> None: + input_frame = nw.from_native(nw_frame_constructor(data)) expected_col = [datetime.strftime(d, fmt) for d in data["a"]] result = input_frame.select(nw.col("a").dt.to_string(fmt).alias("b")) - if any(x in str(constructor) for x in ["pandas_pyarrow", "pyarrow_table", "modin"]): + if any( + x in str(nw_frame_constructor) + for x in ["pandas_pyarrow", "pyarrow_table", "modin"] + ): # PyArrow differs from other libraries, in that %S also shows # the fraction of a second. result = input_frame.select( @@ -78,9 +82,9 @@ def _clean_string_expr(e: Any) -> Any: ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_datetime_series( - constructor_eager: ConstructorEager, data: datetime, expected: str + nw_eager_constructor: ConstructorEager, data: datetime, expected: str ) -> None: - df = constructor_eager({"a": [data]}) + df = nw_eager_constructor({"a": [data]}) result = ( nw.from_native(df, eager_only=True)["a"] .dt.to_string("%Y-%m-%dT%H:%M:%S.%f") @@ -106,14 +110,14 @@ def test_dt_to_string_iso_local_datetime_series( ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_datetime_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, data: datetime, expected: str, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(constructor) or "ibis" in str(constructor): + if "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - df = constructor({"a": [data]}) + df = nw_frame_constructor({"a": [data]}) result = nw.from_native(df).select( b=_clean_string_expr(nw.col("a").dt.to_string("%Y-%m-%dT%H:%M:%S.%f")) @@ -129,9 +133,9 @@ def test_dt_to_string_iso_local_datetime_expr( @pytest.mark.parametrize(("data", "expected"), [(datetime(2020, 1, 9), "2020-01-09")]) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_date_series( - constructor_eager: ConstructorEager, data: datetime, expected: str + nw_eager_constructor: ConstructorEager, data: datetime, expected: str ) -> None: - df = constructor_eager({"a": [data]}) + df = nw_eager_constructor({"a": [data]}) result = nw.from_native(df, eager_only=True)["a"].dt.to_string("%Y-%m-%d").item(0) assert str(result) == expected @@ -139,8 +143,8 @@ def test_dt_to_string_iso_local_date_series( @pytest.mark.parametrize(("data", "expected"), [(datetime(2020, 1, 9), "2020-01-09")]) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_date_expr( - constructor: Constructor, data: datetime, expected: str + nw_frame_constructor: Constructor, data: datetime, expected: str ) -> None: - df = constructor({"a": [data]}) + df = nw_frame_constructor({"a": [data]}) result = nw.from_native(df).select(b=nw.col("a").dt.to_string("%Y-%m-%d")) assert_equal_data(result, {"b": [expected]}) diff --git a/tests/expr_and_series/dt/truncate_test.py b/tests/expr_and_series/dt/truncate_test.py index 40ce18d428..e9a750d39a 100644 --- a/tests/expr_and_series/dt/truncate_test.py +++ b/tests/expr_and_series/dt/truncate_test.py @@ -48,23 +48,27 @@ ) def test_truncate( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, every: str, expected: list[datetime], ) -> None: if every.endswith("ns") and any( - x in str(constructor) for x in ("duckdb", "pyspark", "ibis") + x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail()) - if every.endswith("ns") and "polars" in str(constructor) and POLARS_VERSION < (1, 35): + if ( + every.endswith("ns") + and "polars" in str(nw_frame_constructor) + and POLARS_VERSION < (1, 35) + ): request.applymarker(pytest.mark.xfail()) if any(every.endswith(x) for x in ("mo", "q", "y")) and any( - x in str(constructor) for x in ("dask", "cudf") + x in str(nw_frame_constructor) for x in ("dask", "cudf") ): request.applymarker(pytest.mark.xfail(reason="Not implemented")) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.truncate(every)) assert_equal_data(result, {"a": expected}) @@ -103,26 +107,34 @@ def test_truncate( ) def test_truncate_multiples( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, every: str, expected: list[datetime], ) -> None: - if any(x in str(constructor) for x in ("cudf", "pyspark", "duckdb")): + if any(x in str(nw_frame_constructor) for x in ("cudf", "pyspark", "duckdb")): # Reasons: # - cudf: https://github.com/rapidsai/cudf/issues/18654 # - pyspark/sqlframe: Only multiple 1 is currently supported request.applymarker(pytest.mark.xfail()) - if every.endswith("ns") and any(x in str(constructor) for x in ("duckdb", "ibis")): + if every.endswith("ns") and any( + x in str(nw_frame_constructor) for x in ("duckdb", "ibis") + ): request.applymarker(pytest.mark.xfail()) - if every.endswith("ns") and "polars" in str(constructor) and POLARS_VERSION < (1, 35): + if ( + every.endswith("ns") + and "polars" in str(nw_frame_constructor) + and POLARS_VERSION < (1, 35) + ): request.applymarker(pytest.mark.xfail()) - if any(every.endswith(x) for x in ("mo", "q", "y")) and "dask" in str(constructor): + if any(every.endswith(x) for x in ("mo", "q", "y")) and "dask" in str( + nw_frame_constructor + ): request.applymarker(pytest.mark.xfail(reason="Not implemented")) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").dt.truncate(every)) assert_equal_data(result, {"a": expected}) @@ -157,8 +169,8 @@ def test_truncate_polars_ns(every: str, expected: list[datetime]) -> None: assert_equal_data(result, {"a": expected}) -def test_truncate_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_truncate_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].dt.truncate("1h")) expected = { "a": [datetime(2021, 3, 1, 12, 0, 0, 0), datetime(2020, 1, 2, 2, 0, 0, 0)] @@ -166,15 +178,15 @@ def test_truncate_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_truncate_invalid_interval(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_truncate_invalid_interval(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) msg = "Invalid `every` string" with pytest.raises(ValueError, match=msg): df.select(nw.col("a").dt.truncate("1r")) -def test_truncate_invalid_multiple(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_truncate_invalid_multiple(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) msg = "Only the following multiples are supported" msg_year = "Only multiple 1 is currently supported for 'y' unit" with pytest.raises(ValueError, match=msg): diff --git a/tests/expr_and_series/ewm_test.py b/tests/expr_and_series/ewm_test.py index a3afae154b..5a10c50624 100644 --- a/tests/expr_and_series/ewm_test.py +++ b/tests/expr_and_series/ewm_test.py @@ -9,12 +9,12 @@ def test_ewm_mean_expr( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a", "b").ewm_mean(com=1)) expected = { "a": [1.0, 1.0, 1.5714285714285714], @@ -24,12 +24,12 @@ def test_ewm_mean_expr( def test_ewm_mean_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.ewm_mean(com=1) expected = {"a": [1.0, 1.0, 1.5714285714285714]} assert_equal_data({"a": result}, expected) @@ -50,14 +50,14 @@ def test_ewm_mean_series( ) def test_ewm_mean_expr_adjust( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, adjust: bool, # noqa: FBT001 expected: dict[str, list[float]], ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a", "b").ewm_mean(com=1, adjust=adjust)) assert_equal_data(result, expected) @@ -73,23 +73,23 @@ def test_ewm_mean_nulls( request: pytest.FixtureRequest, ignore_nulls: bool, # noqa: FBT001 expected: dict[str, list[float]], - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin", "cudf")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin", "cudf")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"a": [2.0, 4.0, None, 3.0]})) + df = nw.from_native(nw_eager_constructor({"a": [2.0, 4.0, None, 3.0]})) result = df.select(nw.col("a").ewm_mean(com=1, ignore_nulls=ignore_nulls)) assert_equal_data(result, expected) def test_ewm_mean_params( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin", "cudf")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin", "cudf")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"a": [2, 5, 3]})) + df = nw.from_native(nw_eager_constructor({"a": [2, 5, 3]})) expected: dict[str, list[float | None]] = {"a": [2.0, 4.0, 3.4285714285714284]} assert_equal_data( df.select(nw.col("a").ewm_mean(alpha=0.5, adjust=True, ignore_nulls=True)), diff --git a/tests/expr_and_series/exclude_test.py b/tests/expr_and_series/exclude_test.py index 4aa39478d2..40e3fbbda2 100644 --- a/tests/expr_and_series/exclude_test.py +++ b/tests/expr_and_series/exclude_test.py @@ -21,11 +21,11 @@ ], ) def test_exclude( - constructor: Constructor, exclude_selector: nw.Expr, expected_cols: list[str] + nw_frame_constructor: Constructor, exclude_selector: nw.Expr, expected_cols: list[str] ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(exclude_selector) expected = {col: data[col] for col in expected_cols} diff --git a/tests/expr_and_series/exp_test.py b/tests/expr_and_series/exp_test.py index 7bfcd5c404..407c4843d6 100644 --- a/tests/expr_and_series/exp_test.py +++ b/tests/expr_and_series/exp_test.py @@ -11,15 +11,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_exp_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_exp_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").exp()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_exp_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_exp_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.exp() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/fill_nan_test.py b/tests/expr_and_series/fill_nan_test.py index 5d3ddc8cfc..7245d5fd3e 100644 --- a/tests/expr_and_series/fill_nan_test.py +++ b/tests/expr_and_series/fill_nan_test.py @@ -6,8 +6,10 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_fill_nan(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if "cudf" in str(constructor): +def test_fill_nan( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if "cudf" in str(nw_frame_constructor): request.applymarker( pytest.mark.xfail( reason="https://github.com/narwhals-dev/narwhals/issues/3231", @@ -15,7 +17,7 @@ def test_fill_nan(request: pytest.FixtureRequest, constructor: Constructor) -> N ) ) data_na = {"int": [-1, 1, None]} - df = nw.from_native(constructor(data_na)).select( + df = nw.from_native(nw_frame_constructor(data_na)).select( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") ** 0.5 ) result = df.select(nw.all().fill_nan(None)) @@ -23,11 +25,11 @@ def test_fill_nan(request: pytest.FixtureRequest, constructor: Constructor) -> N assert_equal_data(result, expected) assert result.lazy().collect()["float_na"].null_count() == 2 result = df.select(nw.all().fill_nan(3.0)) - if constructor.is_non_nullable: + if nw_frame_constructor.is_non_nullable: # no nan vs null distinction expected = {"float": [-1.0, 1.0, 3.0], "float_na": [3.0, 1.0, 3.0]} assert result.lazy().collect()["float_na"].null_count() == 0 - elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): expected = {"float": [-1.0, 1.0, None], "float_na": [None, 1.0, None]} assert result.lazy().collect()["float_na"].null_count() == 2 else: @@ -36,16 +38,16 @@ def test_fill_nan(request: pytest.FixtureRequest, constructor: Constructor) -> N assert_equal_data(result, expected) -def test_fill_nan_series(constructor_eager: ConstructorEager) -> None: +def test_fill_nan_series(nw_eager_constructor: ConstructorEager) -> None: data_na = {"int": [-1, 1, None]} - s = nw.from_native(constructor_eager(data_na)).select(float_na=nw.col("int") ** 0.5)[ - "float_na" - ] + s = nw.from_native(nw_eager_constructor(data_na)).select( + float_na=nw.col("int") ** 0.5 + )["float_na"] result = s.fill_nan(999) - if constructor_eager.is_non_nullable: + if nw_eager_constructor.is_non_nullable: # no nan vs null distinction assert_equal_data({"a": result}, {"a": [999.0, 1.0, 999.0]}) - elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): assert_equal_data({"a": result}, {"a": [None, 1.0, None]}) else: assert_equal_data({"a": result}, {"a": [999.0, 1.0, None]}) diff --git a/tests/expr_and_series/fill_null_test.py b/tests/expr_and_series/fill_null_test.py index 213b695176..2e04e40a0b 100644 --- a/tests/expr_and_series/fill_null_test.py +++ b/tests/expr_and_series/fill_null_test.py @@ -20,13 +20,13 @@ from narwhals.typing import FillNullStrategy -def test_fill_null(constructor: Constructor) -> None: +def test_fill_null(nw_frame_constructor: Constructor) -> None: data = { "a": [0.0, None, 2.0, 3.0, 4.0], "b": [1.0, None, None, 5.0, 3.0], "c": [5.0, None, 3.0, 2.0, 1.0], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a", "b", "c").fill_null(value=99)) expected = { @@ -37,14 +37,14 @@ def test_fill_null(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_fill_null_w_aggregate(constructor: Constructor) -> None: - if "dask" in str(constructor) and DASK_VERSION < (2024, 12): +def test_fill_null_w_aggregate(nw_frame_constructor: Constructor) -> None: + if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 12): # Bug in old version of Dask. pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [0.5, None, 2.0, 3.0, 4.5], "b": ["xx", "yy", "zz", None, "yy"]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").fill_null(nw.col("a").mean()), nw.col("b").fill_null("a") @@ -64,13 +64,13 @@ def test_fill_null_pandas_downcast() -> None: assert result["a"].to_native().dtype == "object" -def test_fill_null_series_expression(constructor: Constructor) -> None: +def test_fill_null_series_expression(nw_frame_constructor: Constructor) -> None: data = { "a": [0.0, None, 2.0, 3.0, 4.0], "b": [1.0, None, None, 5.0, 3.0], "c": [5.0, 2.0, None, 2.0, 1.0], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a", "b").fill_null(nw.col("c"))) expected = { @@ -81,9 +81,9 @@ def test_fill_null_series_expression(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_fill_null_exceptions(constructor: Constructor) -> None: +def test_fill_null_exceptions(nw_frame_constructor: Constructor) -> None: data = {"a": [0.0, None, 2.0, 3.0, 4.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(ValueError, match="cannot specify both `value` and `strategy`"): df.with_columns(nw.col("a").fill_null(value=99, strategy="forward")) @@ -98,14 +98,14 @@ def test_fill_null_exceptions(constructor: Constructor) -> None: def test_fill_null_strategies_with_limit_as_none( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) data_limits = { @@ -113,7 +113,7 @@ def test_fill_null_strategies_with_limit_as_none( "b": ["a", None, None, None, "b", "c", None, None, None, "d"], "idx": list(range(10)), } - df = nw.from_native(constructor(data_limits)) + df = nw.from_native(nw_frame_constructor(data_limits)) expected_forward = { "a": [1, 1, 1, 1, 5, 6, 6, 6, 6, 10], @@ -121,9 +121,9 @@ def test_fill_null_strategies_with_limit_as_none( "idx": list(range(10)), } if ( - "pandas_pyarrow_constructor" in str(constructor) - or "modin" in str(constructor) - or "dask" in str(constructor) + "pandas_pyarrow_constructor" in str(nw_frame_constructor) + or "modin" in str(nw_frame_constructor) + or "dask" in str(nw_frame_constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -155,9 +155,9 @@ def test_fill_null_strategies_with_limit_as_none( "idx": list(range(10)), } if ( - "pandas_pyarrow_constructor" in str(constructor) - or "modin" in str(constructor) - or "dask" in str(constructor) + "pandas_pyarrow_constructor" in str(nw_frame_constructor) + or "modin" in str(nw_frame_constructor) + or "dask" in str(nw_frame_constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -185,21 +185,21 @@ def test_fill_null_strategies_with_limit_as_none( def test_fill_null_limits( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) context: Any = ( pytest.raises(NotImplementedError, match="The limit keyword is not supported") - if "cudf" in str(constructor) + if "cudf" in str(nw_frame_constructor) else warnings.catch_warnings() - if "modin" in str(constructor) + if "modin" in str(nw_frame_constructor) else does_not_raise() ) data_limits = { @@ -207,9 +207,9 @@ def test_fill_null_limits( "b": ["a", None, None, None, "b", "c", None, None, None, "d"], "idx": list(range(10)), } - df = nw.from_native(constructor(data_limits)) + df = nw.from_native(nw_frame_constructor(data_limits)) with context: - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): warnings.filterwarnings( "ignore", message="The 'downcast' keyword in fillna is deprecated" ) @@ -236,9 +236,9 @@ def test_fill_null_limits( assert_equal_data(result_backward, expected_backward) -def test_fill_null_series(constructor_eager: ConstructorEager) -> None: +def test_fill_null_series(nw_eager_constructor: ConstructorEager) -> None: data_series_float = {"a": [0.0, 1, None, 2, None, 3]} - df_float = nw.from_native(constructor_eager(data_series_float), eager_only=True) + df_float = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) expected_float = {"a_zero_digit": [0.0, 1, 0, 2, 0, 3]} result_float = df_float.select(a_zero_digit=df_float["a"].fill_null(value=0)) @@ -246,7 +246,7 @@ def test_fill_null_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result_float, expected_float) data_series_str = {"a": ["a", None, "c", None, "e"]} - df_str = nw.from_native(constructor_eager(data_series_str), eager_only=True) + df_str = nw.from_native(nw_eager_constructor(data_series_str), eager_only=True) expected_str = {"a_z_str": ["a", "z", "c", "z", "e"]} @@ -255,22 +255,22 @@ def test_fill_null_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result_str, expected_str) -def test_fill_null_series_limits(constructor_eager: ConstructorEager) -> None: +def test_fill_null_series_limits(nw_eager_constructor: ConstructorEager) -> None: context: Any = ( pytest.raises(NotImplementedError, match="The limit keyword is not supported") - if "cudf" in str(constructor_eager) + if "cudf" in str(nw_eager_constructor) else warnings.catch_warnings() - if "modin" in str(constructor_eager) + if "modin" in str(nw_eager_constructor) else does_not_raise() ) data_series_float = { "a": [0.0, 1, None, None, 2, None, None, 3], "b": ["", "a", None, None, "c", None, None, "e"], } - df = nw.from_native(constructor_eager(data_series_float), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) with context: - if "modin" in str(constructor_eager): + if "modin" in str(nw_eager_constructor): warnings.filterwarnings( "ignore", message="The 'downcast' keyword in fillna is deprecated" ) @@ -298,18 +298,18 @@ def test_fill_null_series_limits(constructor_eager: ConstructorEager) -> None: assert_equal_data(result_backward, expected_backward) -def test_fill_null_series_limit_as_none(constructor_eager: ConstructorEager) -> None: +def test_fill_null_series_limit_as_none(nw_eager_constructor: ConstructorEager) -> None: data_series = {"a": [1, None, None, None, 5, 6, None, None, None, 10]} - df = nw.from_native(constructor_eager(data_series), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_series), eager_only=True) expected_forward = { "a_forward": [1, 1, 1, 1, 5, 6, 6, 6, 6, 10], "a_backward": [1, 5, 5, 5, 5, 6, 10, 10, 10, 10], } if ( - "pandas_pyarrow_constructor" in str(constructor_eager) - or "modin" in str(constructor_eager) - or "dask" in str(constructor_eager) + "pandas_pyarrow_constructor" in str(nw_eager_constructor) + or "modin" in str(nw_eager_constructor) + or "dask" in str(nw_eager_constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -335,7 +335,7 @@ def test_fill_null_series_limit_as_none(constructor_eager: ConstructorEager) -> data_series_str = {"a": ["a", None, None, None, "b", "c", None, None, None, "d"]} - df_str = nw.from_native(constructor_eager(data_series_str), eager_only=True) + df_str = nw.from_native(nw_eager_constructor(data_series_str), eager_only=True) expected_forward_str = { "a_forward": ["a", "a", "a", "a", "b", "c", "c", "c", "c", "d"], @@ -343,9 +343,9 @@ def test_fill_null_series_limit_as_none(constructor_eager: ConstructorEager) -> } if ( - "pandas_pyarrow_constructor" in str(constructor_eager) - or "modin" in str(constructor_eager) - or "dask" in str(constructor_eager) + "pandas_pyarrow_constructor" in str(nw_eager_constructor) + or "modin" in str(nw_eager_constructor) + or "dask" in str(nw_eager_constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -369,9 +369,9 @@ def test_fill_null_series_limit_as_none(constructor_eager: ConstructorEager) -> assert_equal_data(result_forward_str, expected_forward_str) -def test_fill_null_series_exceptions(constructor_eager: ConstructorEager) -> None: +def test_fill_null_series_exceptions(nw_eager_constructor: ConstructorEager) -> None: data_series_float = {"a": [0.0, 1, None, 2, None, 3]} - df_float = nw.from_native(constructor_eager(data_series_float), eager_only=True) + df_float = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) with pytest.raises(ValueError, match="cannot specify both `value` and `strategy`"): df_float.select(a_zero_digit=df_float["a"].fill_null(value=0, strategy="forward")) @@ -388,16 +388,16 @@ def test_fill_null_series_exceptions(constructor_eager: ConstructorEager) -> Non def test_fill_null_strategies_with_partition_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "dask", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "ibis")): request.applymarker(pytest.mark.xfail) - if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() @@ -406,7 +406,7 @@ def test_fill_null_strategies_with_partition_by( "values": [1, None, None, 2, None, 3, None, None, 4], "idx": list(range(9)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) # Forward fill within each group result_forward = df.with_columns( @@ -447,21 +447,21 @@ def test_fill_null_strategies_with_partition_by( ], ) def test_fill_null_expr_limits( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, values: list[int | None], strategy: FillNullStrategy, limit: int, expected: list[int | None], request: pytest.FixtureRequest, ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): reason = "The limit keyword is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) data = {"a": values} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.with_columns(nw.col("a").fill_null(strategy=strategy, limit=limit)) assert_equal_data(result, {"a": expected}) diff --git a/tests/expr_and_series/filter_test.py b/tests/expr_and_series/filter_test.py index 5f300ed4b8..ccfcdb5c7b 100644 --- a/tests/expr_and_series/filter_test.py +++ b/tests/expr_and_series/filter_test.py @@ -20,15 +20,15 @@ } -def test_filter(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_filter(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").filter(nw.col("i") < 2, nw.col("c") == 5)) expected = {"a": [0]} assert_equal_data(result, expected) -def test_filter_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_filter_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].filter((df["i"] < 2) & (df["c"] == 5))) expected = {"a": [0]} assert_equal_data(result, expected) @@ -37,8 +37,8 @@ def test_filter_series(constructor_eager: ConstructorEager) -> None: assert_equal_data({"a": result_s}, expected) -def test_filter_constraints(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_filter_constraints(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result_added = df.filter(nw.col("i") < 4, b=3) expected = {"i": [2], "a": [2], "b": [3], "c": [3]} assert_equal_data(result_added, expected) @@ -46,10 +46,10 @@ def test_filter_constraints(constructor: Constructor) -> None: assert_equal_data(result_only, expected) -def test_filter_windows(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_filter_windows(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.filter(nw.col("i") == nw.col("i").min()) expected = {"i": [0], "a": [0], "b": [1], "c": [5]} assert_equal_data(result, expected) @@ -60,12 +60,12 @@ def test_filter_windows(constructor: Constructor) -> None: def test_filter_windows_over( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail()) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.filter(nw.col("i") == nw.col("i").min().over("b")).sort("i") assert_equal_data(result, expected_over) diff --git a/tests/expr_and_series/first_last_test.py b/tests/expr_and_series/first_last_test.py index 0dab322cd1..e5f323aa82 100644 --- a/tests/expr_and_series/first_last_test.py +++ b/tests/expr_and_series/first_last_test.py @@ -35,20 +35,20 @@ @single_cases def test_first_last_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.first() assert_equal_data({col: [result]}, {col: [expected_first]}) result = series.last() assert_equal_data({col: [result]}, {col: [expected_last]}) -def test_first_last_series_empty(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_first_last_series_empty(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] series = series.filter(series > 50) result = series.first() assert result is None @@ -58,12 +58,12 @@ def test_first_last_series_empty(constructor_eager: ConstructorEager) -> None: @single_cases def test_first_last_expr_select( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select( nw.col(col).first().name.suffix("_first"), nw.col(col).last().name.suffix("_last") ) @@ -74,12 +74,12 @@ def test_first_last_expr_select( @single_cases def test_first_expr_with_columns( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.with_columns( nw.col(col).first().name.suffix("_first"), nw.col(col).last().name.suffix("_last") ).select(nw.selectors.matches("first|last")) @@ -93,22 +93,22 @@ def test_first_expr_with_columns( def test_first_last_expr_over_order_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(constructor) for x in ("pyspark", "dask")): + if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): reason = "Need to pass dtype when passing pd.NA or None" request.applymarker(pytest.mark.xfail(reason=reason)) frame = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 1, 2], "b": [4, 5, 6], @@ -150,24 +150,24 @@ def test_first_last_expr_over_order_by( def test_first_expr_over_order_by_partition_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(constructor) for x in ("pyspark", "dask")): + if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): # https://github.com/ibis-project/ibis/issues/11656 request.applymarker(pytest.mark.xfail) frame = nw.from_native( - constructor( + nw_frame_constructor( {"a": [1, 1, 2], "b": [4, 5, 6], "c": [None, 7, 8], "i": [1, None, 2]} ) ) @@ -189,14 +189,14 @@ def test_first_expr_over_order_by_partition_by( def test_first_expr_in_group_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("spark", "dask")): + if any(x in str(nw_frame_constructor) for x in ("spark", "dask")): # ibis: https://github.com/ibis-project/ibis/issues/11656 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): pytest.skip() data = { "grp": [1, 1, 1, 2], @@ -206,7 +206,7 @@ def test_first_expr_in_group_by( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.group_by("grp") .agg( @@ -246,11 +246,11 @@ def test_first_expr_in_group_by( def test_first_expr_broadcasting( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("spark", "dask")): + if any(x in str(nw_frame_constructor) for x in ("spark", "dask")): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { @@ -261,7 +261,7 @@ def test_first_expr_broadcasting( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( "idx", "idx2", nw.col("a", "b", "c").first(order_by="idx").name.suffix("_first") ).sort("idx", "idx2") @@ -289,9 +289,9 @@ def test_first_expr_broadcasting( def test_first_expr_invalid( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) data = { "grp": [1, 1, 1, 2], @@ -301,31 +301,31 @@ def test_first_expr_invalid( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(InvalidOperationError, match="expression which isn't orderable"): df.select("idx", "idx2", nw.col("a").first(order_by="idx").over(order_by="idx2")) def test_first_last_different_orders( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if any(x in str(constructor) for x in ("pyspark", "dask")): + if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() context = ( pytest.raises(NotImplementedError, match="Only one `order_by` can") - if "pandas" in str(constructor) or "pyarrow" in str(constructor) + if "pandas" in str(nw_frame_constructor) or "pyarrow" in str(nw_frame_constructor) else does_not_raise() ) frame = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 1, 2], "b": [4, 5, 6], diff --git a/tests/expr_and_series/floor_ceil_test.py b/tests/expr_and_series/floor_ceil_test.py index ae0df72712..d7871df9a6 100644 --- a/tests/expr_and_series/floor_ceil_test.py +++ b/tests/expr_and_series/floor_ceil_test.py @@ -6,9 +6,9 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_floor_expr(constructor: Constructor) -> None: +def test_floor_expr(nw_frame_constructor: Constructor) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) expected_data = {"a": [1.0, 2.0, 3.0, -1.0]} @@ -17,9 +17,9 @@ def test_floor_expr(constructor: Constructor) -> None: assert_equal_data(result_frame, expected_data) -def test_ceil_expr(constructor: Constructor) -> None: +def test_ceil_expr(nw_frame_constructor: Constructor) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) expected_data = {"a": [2.0, 3.0, 4.0, 0.0]} @@ -27,9 +27,9 @@ def test_ceil_expr(constructor: Constructor) -> None: assert_equal_data(result_frame, expected_data) -def test_floor_series(constructor_eager: ConstructorEager) -> None: +def test_floor_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {"a": [1.0, 2.0, 3.0, -1.0]} @@ -38,9 +38,9 @@ def test_floor_series(constructor_eager: ConstructorEager) -> None: assert_equal_data({"a": result_series}, expected_data) -def test_ceil_series(constructor_eager: ConstructorEager) -> None: +def test_ceil_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {"a": [2.0, 3.0, 4.0, 0.0]} diff --git a/tests/expr_and_series/format_test.py b/tests/expr_and_series/format_test.py index 5bd4ba75a9..e6ac2bef19 100644 --- a/tests/expr_and_series/format_test.py +++ b/tests/expr_and_series/format_test.py @@ -6,9 +6,9 @@ from tests.utils import Constructor, assert_equal_data -def test_format(constructor: Constructor) -> None: +def test_format(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor( + nw_frame_constructor( { "name": ["bob", "alice", "dodo"], "surname": ["builder", "wonderlander", "extinct"], diff --git a/tests/expr_and_series/horizontal_broadcasts_test.py b/tests/expr_and_series/horizontal_broadcasts_test.py index 6c6bb8966d..18cc88de85 100644 --- a/tests/expr_and_series/horizontal_broadcasts_test.py +++ b/tests/expr_and_series/horizontal_broadcasts_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_sumh_broadcasting(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_sumh_broadcasting(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6], "i": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns( any=nw.any_horizontal(nw.sum("a", "b").cast(nw.Boolean), ignore_nulls=True), all=nw.all_horizontal(nw.sum("a", "b").cast(nw.Boolean), ignore_nulls=True), diff --git a/tests/expr_and_series/is_between_test.py b/tests/expr_and_series/is_between_test.py index 6cec08ad64..f99f76438a 100644 --- a/tests/expr_and_series/is_between_test.py +++ b/tests/expr_and_series/is_between_test.py @@ -20,20 +20,20 @@ ], ) def test_is_between( - constructor: Constructor, + nw_frame_constructor: Constructor, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [1, 4, 2, 5]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_between(1, 5, closed=closed)) expected_dict = {"a": expected} assert_equal_data(result, expected_dict) -def test_is_between_expressified(constructor: Constructor) -> None: +def test_is_between_expressified(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 4, 2, 5], "b": [0, 5, 2, 4], "c": [9, 9, 9, 9]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_between(nw.col("b") * 0.9, "c")) expected_dict = {"a": [True, False, True, True]} assert_equal_data(result, expected_dict) @@ -49,20 +49,20 @@ def test_is_between_expressified(constructor: Constructor) -> None: ], ) def test_is_between_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [1, 4, 2, 5]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.with_columns(a=df["a"].is_between(1, 5, closed=closed)) expected_dict = {"a": expected} assert_equal_data(result, expected_dict) -def test_is_between_expressified_series(constructor_eager: ConstructorEager) -> None: +def test_is_between_expressified_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 4, 2, 5], "b": [0, 5, 2, 4], "c": [9, 9, 9, 9]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].is_between(df["b"], df["c"]).to_frame() expected_dict = {"a": [True, False, True, True]} assert_equal_data(result, expected_dict) @@ -78,12 +78,12 @@ def test_is_between_expressified_series(constructor_eager: ConstructorEager) -> ], ) def test_is_between_datetimes( - constructor: Constructor, + nw_frame_constructor: Constructor, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [datetime(2020, 1, 1), datetime(2020, 6, 1)]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").is_between(datetime(2020, 3, 1), datetime(2020, 6, 1), closed=closed) ) @@ -91,7 +91,7 @@ def test_is_between_datetimes( assert_equal_data(result, expected_dict) -def test_is_between_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_is_between_invalid(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(nw.col("a").is_between(nw.all(), nw.col("a", "b"))) diff --git a/tests/expr_and_series/is_close_test.py b/tests/expr_and_series/is_close_test.py index 6cfdb94657..5dcbf68d70 100644 --- a/tests/expr_and_series/is_close_test.py +++ b/tests/expr_and_series/is_close_test.py @@ -35,8 +35,10 @@ # Exceptions -def test_is_close_series_raise_non_numeric(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_is_close_series_raise_non_numeric( + nw_eager_constructor: ConstructorEager, +) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) x, y = df["non_numeric"], df["y"] msg = "`is_close` operation not supported for dtype" @@ -46,9 +48,9 @@ def test_is_close_series_raise_non_numeric(constructor_eager: ConstructorEager) @pytest.mark.parametrize("rel_tol", [1e-09, 999]) def test_is_close_raise_negative_abs_tol( - constructor_eager: ConstructorEager, rel_tol: float + nw_eager_constructor: ConstructorEager, rel_tol: float ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) x, y = df["x"], df["y"] abs_tol = -2 @@ -62,9 +64,9 @@ def test_is_close_raise_negative_abs_tol( @pytest.mark.parametrize("rel_tol", [-0.0001, 1.0, 1.1]) def test_is_close_raise_invalid_rel_tol( - constructor_eager: ConstructorEager, rel_tol: float + nw_eager_constructor: ConstructorEager, rel_tol: float ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) x, y = df["x"], df["y"] msg = rf"`rel_tol` must be in the range \[0, 1\) but got {rel_tol}" @@ -98,14 +100,14 @@ def test_is_close_raise_invalid_rel_tol( # Series @cases_columnar def test_is_close_series_with_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, abs_tol: float, rel_tol: float, *, nans_equal: bool, expected: list[Any], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) x, y = df["x"], df["y"] nulls = nw.new_series( "nulls", [None] * len(x), nw.Float64(), backend=df.implementation @@ -114,9 +116,9 @@ def test_is_close_series_with_series( y = y.zip_with(y != NAN_PLACEHOLDER, y**0.5).zip_with(y != NULL_PLACEHOLDER, nulls) result = x.is_close(y, abs_tol=abs_tol, rel_tol=rel_tol, nans_equal=nans_equal) - if constructor_eager.is_non_nullable: + if nw_eager_constructor.is_non_nullable: expected = [v if v is not None else nans_equal for v in expected] - elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -126,7 +128,7 @@ def test_is_close_series_with_series( @cases_scalar def test_is_close_series_with_scalar( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, other: NumericLiteral, abs_tol: float, rel_tol: float, @@ -134,7 +136,7 @@ def test_is_close_series_with_scalar( nans_equal: bool, expected: list[Any], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) y = df["y"] nulls = nw.new_series( "nulls", [None] * len(y), nw.Float64(), backend=df.implementation @@ -142,9 +144,9 @@ def test_is_close_series_with_scalar( y = y.zip_with(y != NAN_PLACEHOLDER, y**0.5).zip_with(y != NULL_PLACEHOLDER, nulls) result = y.is_close(other, abs_tol=abs_tol, rel_tol=rel_tol, nans_equal=nans_equal) - if constructor_eager.is_non_nullable: + if nw_eager_constructor.is_non_nullable: expected = [v if v is not None else False for v in expected] - elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -156,14 +158,14 @@ def test_is_close_series_with_scalar( @cases_columnar def test_is_close_expr_with_expr( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, abs_tol: float, rel_tol: float, *, nans_equal: bool, expected: list[Any], ) -> None: - if "sqlframe" in str(constructor): + if "sqlframe" in str(nw_frame_constructor): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='" @@ -172,7 +174,7 @@ def test_is_close_expr_with_expr( x, y = nw.col("x"), nw.col("y") result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_columns( x=nw.when(x != NAN_PLACEHOLDER).then(x).otherwise(x**0.5), y=nw.when(y != NAN_PLACEHOLDER).then(y).otherwise(y**0.5), @@ -187,9 +189,9 @@ def test_is_close_expr_with_expr( ) .sort("idx") ) - if constructor.is_non_nullable: + if nw_frame_constructor.is_non_nullable: expected = [v if v is not None else nans_equal for v in expected] - elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -200,7 +202,7 @@ def test_is_close_expr_with_expr( @cases_scalar def test_is_close_expr_with_scalar( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, other: NumericLiteral, abs_tol: float, rel_tol: float, @@ -208,7 +210,7 @@ def test_is_close_expr_with_scalar( nans_equal: bool, expected: list[Any], ) -> None: - if "sqlframe" in str(constructor): + if "sqlframe" in str(nw_frame_constructor): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='" @@ -217,7 +219,7 @@ def test_is_close_expr_with_scalar( y = nw.col("y") result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_columns(y=nw.when(y != NAN_PLACEHOLDER).then(y).otherwise(y**0.5)) .with_columns(y=nw.when(y != NULL_PLACEHOLDER).then(y)) .select( @@ -228,9 +230,9 @@ def test_is_close_expr_with_scalar( ) .sort("idx") ) - if constructor.is_non_nullable: + if nw_frame_constructor.is_non_nullable: expected = [v if v is not None else False for v in expected] - elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -250,8 +252,8 @@ def test_is_close_pandas_unnamed() -> None: assert res.name == "ab" -def test_issue_3474_series_decimal(constructor_eager: ConstructorEager) -> None: - frame = nw.from_native(constructor_eager({"a": [0, 1, 2]})) +def test_issue_3474_series_decimal(nw_eager_constructor: ConstructorEager) -> None: + frame = nw.from_native(nw_eager_constructor({"a": [0, 1, 2]})) if frame.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) @@ -263,9 +265,9 @@ def test_issue_3474_series_decimal(constructor_eager: ConstructorEager) -> None: def test_issue_3474_expr_decimal( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("dask", "sqlframe")): + if any(x in str(nw_frame_constructor) for x in ("dask", "sqlframe")): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "SQLFrame: duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='\n" @@ -273,7 +275,7 @@ def test_issue_3474_expr_decimal( ) request.applymarker(pytest.mark.xfail(reason=reason)) - frame = nw.from_native(constructor({"a": [0, 1, 2]})) + frame = nw.from_native(nw_frame_constructor({"a": [0, 1, 2]})) if frame.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) diff --git a/tests/expr_and_series/is_duplicated_test.py b/tests/expr_and_series/is_duplicated_test.py index 42f07a91e5..c99f990ff8 100644 --- a/tests/expr_and_series/is_duplicated_test.py +++ b/tests/expr_and_series/is_duplicated_test.py @@ -6,31 +6,31 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_is_duplicated_expr(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_is_duplicated_expr(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").is_duplicated(), "index").sort("index") expected = {"a": [True, True, False], "b": [False, False, False], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_duplicated_w_nulls_expr(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_is_duplicated_w_nulls_expr(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, None], "b": [1, None, None], "index": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").is_duplicated(), "index").sort("index") expected = {"a": [True, True, False], "b": [False, True, True], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_duplicated_series(constructor_eager: ConstructorEager) -> None: +def test_is_duplicated_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.is_duplicated() expected = {"a": [True, True, False]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_finite_test.py b/tests/expr_and_series/is_finite_test.py index b2a36d5ed7..bff9923e58 100644 --- a/tests/expr_and_series/is_finite_test.py +++ b/tests/expr_and_series/is_finite_test.py @@ -11,60 +11,65 @@ @pytest.mark.filterwarnings("ignore:invalid value encountered in cast") -def test_is_finite_expr(constructor: Constructor) -> None: +def test_is_finite_expr(nw_frame_constructor: Constructor) -> None: if any( - x in str(constructor) + x in str(nw_frame_constructor) for x in ("polars", "pyarrow_table", "duckdb", "pyspark", "ibis") ): expected = {"a": [False, False, True, None]} elif any( - x in str(constructor) for x in ("pandas_constructor", "dask", "modin_constructor") + x in str(nw_frame_constructor) + for x in ("pandas_constructor", "dask", "modin_constructor") ): expected = {"a": [False, False, True, False]} else: # pandas_nullable_constructor, pandas_pyarrow_constructor, modin_pyarrrow_constructor # Here, the 'nan' and None get mangled upon dataframe construction. expected = {"a": [None, False, True, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_finite()) assert_equal_data(result, expected) @pytest.mark.filterwarnings("ignore:invalid value encountered in cast") -def test_is_finite_series(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) or "pyarrow_table" in str(constructor_eager): +def test_is_finite_series(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) or "pyarrow_table" in str( + nw_eager_constructor + ): expected = {"a": [False, False, True, None]} elif ( - "pandas_constructor" in str(constructor_eager) - or "dask" in str(constructor_eager) - or "modin_constructor" in str(constructor_eager) + "pandas_constructor" in str(nw_eager_constructor) + or "dask" in str(nw_eager_constructor) + or "modin_constructor" in str(nw_eager_constructor) ): expected = {"a": [False, False, True, False]} else: # pandas_nullable_constructor, pandas_pyarrow_constructor, modin_pyarrrow_constructor expected = {"a": [None, False, True, None]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"a": df["a"].is_finite()} assert_equal_data(result, expected) -def test_is_finite_integer_column(constructor: Constructor) -> None: +def test_is_finite_integer_column(nw_frame_constructor: Constructor) -> None: # Test for https://github.com/narwhals-dev/narwhals/issues/3255 - df = nw.from_native(constructor({"a": [1, 2, 3]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) result = df.select(nw.col("a").is_finite()) assert_equal_data(result, {"a": [True, True, True]}) @pytest.mark.parametrize("data", [[1, 2, None], [1.0, 2.0, None]]) -def test_is_finite_column_with_null(constructor: Constructor, data: list[float]) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): +def test_is_finite_column_with_null( + nw_frame_constructor: Constructor, data: list[float] +) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip("need newer polars version") - df = nw.from_native(constructor({"a": data})) + df = nw.from_native(nw_frame_constructor({"a": data})) result = df.select(nw.col("a").is_finite()) expected: dict[str, list[Any]] - if constructor.is_non_nullable: + if nw_frame_constructor.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = {"a": [True, True, False]} else: diff --git a/tests/expr_and_series/is_first_distinct_test.py b/tests/expr_and_series/is_first_distinct_test.py index 6f0501b03c..6c7e4c63c1 100644 --- a/tests/expr_and_series/is_first_distinct_test.py +++ b/tests/expr_and_series/is_first_distinct_test.py @@ -14,8 +14,8 @@ data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1]} -def test_is_first_distinct_expr(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_is_first_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.all().is_first_distinct()) expected = { "a": [True, False, True, True, False], @@ -24,13 +24,13 @@ def test_is_first_distinct_expr(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_is_first_distinct_expr_lazy(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): +def test_is_first_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("a", "b").is_first_distinct().over(order_by="i"), "i") .sort("i") @@ -43,13 +43,13 @@ def test_is_first_distinct_expr_lazy(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_is_first_distinct_expr_lazy_w_nulls(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): +def test_is_first_distinct_expr_lazy_w_nulls(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, None, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("a", "b").is_first_distinct().over(order_by="i"), "i") .sort("i") @@ -63,16 +63,19 @@ def test_is_first_distinct_expr_lazy_w_nulls(constructor: Constructor) -> None: def test_is_first_distinct_expr_lazy_grouped( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pandas", "pyarrow", "cudf", "modin")): + if any( + x in str(nw_frame_constructor) + for x in ("dask", "pandas", "pyarrow", "cudf", "modin") + ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 2, 2], "b": [1, 3, 3, 2, 3], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("b").is_first_distinct().over("a", order_by="i"), "i") .sort("i") @@ -82,8 +85,8 @@ def test_is_first_distinct_expr_lazy_grouped( assert_equal_data(result, expected) -def test_is_first_distinct_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_is_first_distinct_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.is_first_distinct() expected = {"a": [True, False, True, True, False]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_in_test.py b/tests/expr_and_series/is_in_test.py index 2ae6cabea5..9aab4adbed 100644 --- a/tests/expr_and_series/is_in_test.py +++ b/tests/expr_and_series/is_in_test.py @@ -10,32 +10,32 @@ data = {"a": [1, 4, 2, 5]} -def test_expr_is_in(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_expr_is_in(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_in([4, 5])) expected = {"a": [False, True, False, True]} assert_equal_data(result, expected) -def test_expr_is_in_empty_list(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_expr_is_in_empty_list(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_in([])) expected = {"a": [False, False, False, False]} assert_equal_data(result, expected) -def test_ser_is_in(constructor_eager: ConstructorEager) -> None: - ser = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_ser_is_in(nw_eager_constructor: ConstructorEager) -> None: + ser = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = {"a": ser.is_in([4, 5])} expected = {"a": [False, True, False, True]} assert_equal_data(result, expected) -def test_is_in_other(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_is_in_other(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) msg = re.escape( "Narwhals `is_in` doesn't accept expressions as an argument, as opposed to " "Polars. You should provide an iterable instead." @@ -44,9 +44,9 @@ def test_is_in_other(constructor: Constructor) -> None: nw.from_native(df_raw).with_columns(contains=nw.col("a").is_in("sets")) -def test_filter_is_in_with_series(constructor_eager: ConstructorEager) -> None: +def test_filter_is_in_with_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 4, 2, 5], "b": [1, 0, 2, 0]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.filter(nw.col("a").is_in(df["b"])) expected = {"a": [1, 2], "b": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/is_last_distinct_test.py b/tests/expr_and_series/is_last_distinct_test.py index b4a96b5b9f..56268742d9 100644 --- a/tests/expr_and_series/is_last_distinct_test.py +++ b/tests/expr_and_series/is_last_distinct_test.py @@ -14,8 +14,8 @@ data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1]} -def test_is_last_distinct_expr(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_is_last_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.all().is_last_distinct()) expected = { "a": [False, True, False, True, True], @@ -24,12 +24,12 @@ def test_is_last_distinct_expr(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_is_last_distinct_expr_all(constructor_eager: ConstructorEager) -> None: +def test_is_last_distinct_expr_all(nw_eager_constructor: ConstructorEager) -> None: # https://github.com/narwhals-dev/narwhals/issues/2268 - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 9): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 9): pytest.skip(reason="too old version") data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.all().is_last_distinct().over(order_by="i")) expected = { "a": [False, True, False, True, True], @@ -39,14 +39,14 @@ def test_is_last_distinct_expr_all(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_is_last_distinct_expr_lazy(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): +def test_is_last_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, None, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("a", "b").is_last_distinct().over(order_by="i"), "i") .sort("i") @@ -60,18 +60,21 @@ def test_is_last_distinct_expr_lazy(constructor: Constructor) -> None: def test_is_last_distinct_expr_lazy_grouped( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("pandas", "pyarrow", "dask", "cudf", "modin")): + if any( + x in str(nw_frame_constructor) + for x in ("pandas", "pyarrow", "dask", "cudf", "modin") + ): # non-elementary group-by agg request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("b").is_last_distinct().over("a", order_by="i"), "i") .sort("i") @@ -82,17 +85,20 @@ def test_is_last_distinct_expr_lazy_grouped( def test_is_last_distinct_expr_lazy_grouped_nulls( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("pandas", "pyarrow", "dask", "cudf", "modin")): + if any( + x in str(nw_frame_constructor) + for x in ("pandas", "pyarrow", "dask", "cudf", "modin") + ): # non-elementary group-by agg request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col("b").is_last_distinct().over("a", order_by="i"), "i") .sort("i") @@ -102,8 +108,8 @@ def test_is_last_distinct_expr_lazy_grouped_nulls( assert_equal_data(result, expected) -def test_is_last_distinct_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_is_last_distinct_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.is_last_distinct() expected = {"a": [False, True, False, True, True]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_nan_test.py b/tests/expr_and_series/is_nan_test.py index 948b800a9b..01907aad0e 100644 --- a/tests/expr_and_series/is_nan_test.py +++ b/tests/expr_and_series/is_nan_test.py @@ -8,9 +8,9 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_nan(constructor: Constructor) -> None: +def test_nan(nw_frame_constructor: Constructor) -> None: data_na = {"int": [-1, 1, None]} - df = nw.from_native(constructor(data_na)).with_columns( + df = nw.from_native(nw_frame_constructor(data_na)).with_columns( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") ** 0.5 ) result = df.select( @@ -20,14 +20,14 @@ def test_nan(constructor: Constructor) -> None: ) expected: dict[str, list[Any]] - if constructor.is_non_nullable: + if nw_frame_constructor.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = { "int": [False, False, True], "float": [False, False, True], "float_na": [True, False, True], } - elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): # NaN values are coerced into NA for nullable datatypes by default expected = { "int": [False, False, None], @@ -45,9 +45,9 @@ def test_nan(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_nan_series(constructor_eager: ConstructorEager) -> None: +def test_nan_series(nw_eager_constructor: ConstructorEager) -> None: data_na = {"int": [0, 1, None]} - df = nw.from_native(constructor_eager(data_na), eager_only=True).with_columns( + df = nw.from_native(nw_eager_constructor(data_na), eager_only=True).with_columns( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") / nw.col("int") ) @@ -57,14 +57,14 @@ def test_nan_series(constructor_eager: ConstructorEager) -> None: "float_na": df["float_na"].is_nan(), } expected: dict[str, list[Any]] - if constructor_eager.is_non_nullable: + if nw_eager_constructor.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = { "int": [False, False, True], "float": [False, False, True], "float_na": [True, False, True], } - elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): + elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): # NaN values are coerced into NA for nullable datatypes by default expected = { "int": [False, False, None], @@ -82,13 +82,15 @@ def test_nan_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_nan_non_float(constructor: Constructor, request: pytest.FixtureRequest) -> None: +def test_nan_non_float( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: pytest.importorskip("pyarrow") if ( - ("pyspark" in str(constructor)) - or "duckdb" in str(constructor) - or "ibis" in str(constructor) + ("pyspark" in str(nw_frame_constructor)) + or "duckdb" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) from pyarrow.lib import ArrowNotImplementedError @@ -96,11 +98,11 @@ def test_nan_non_float(constructor: Constructor, request: pytest.FixtureRequest) from narwhals.exceptions import InvalidOperationError data = {"a": ["x", "y"]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) exc = ( ArrowNotImplementedError - if "pyarrow_table" in str(constructor) + if "pyarrow_table" in str(nw_frame_constructor) else InvalidOperationError ) @@ -108,18 +110,18 @@ def test_nan_non_float(constructor: Constructor, request: pytest.FixtureRequest) df.select(nw.col("a").is_nan()).lazy().collect() -def test_nan_non_float_series(constructor_eager: ConstructorEager) -> None: +def test_nan_non_float_series(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("pyarrow") from pyarrow.lib import ArrowNotImplementedError from narwhals.exceptions import InvalidOperationError data = {"a": ["x", "y"]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) exc = ( ArrowNotImplementedError - if "pyarrow_table" in str(constructor_eager) + if "pyarrow_table" in str(nw_eager_constructor) else InvalidOperationError ) diff --git a/tests/expr_and_series/is_null_test.py b/tests/expr_and_series/is_null_test.py index 7542af4513..76dfef0bda 100644 --- a/tests/expr_and_series/is_null_test.py +++ b/tests/expr_and_series/is_null_test.py @@ -4,19 +4,19 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_null(constructor: Constructor) -> None: +def test_null(nw_frame_constructor: Constructor) -> None: data_na = {"a": [None, 3, 2], "z": [7.0, None, None]} expected = {"a": [True, False, False], "z": [True, False, False]} - df = nw.from_native(constructor(data_na)) + df = nw.from_native(nw_frame_constructor(data_na)) result = df.select(nw.col("a").is_null(), ~nw.col("z").is_null()) assert_equal_data(result, expected) -def test_null_series(constructor_eager: ConstructorEager) -> None: +def test_null_series(nw_eager_constructor: ConstructorEager) -> None: data_na = {"a": [None, 3, 2], "z": [7.0, None, None]} expected = {"a": [True, False, False], "z": [True, False, False]} - df = nw.from_native(constructor_eager(data_na), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) result = {"a": df["a"].is_null(), "z": ~df["z"].is_null()} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/is_unique_test.py b/tests/expr_and_series/is_unique_test.py index 2df0518360..14ceffa7b7 100644 --- a/tests/expr_and_series/is_unique_test.py +++ b/tests/expr_and_series/is_unique_test.py @@ -6,47 +6,50 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_is_unique_expr(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_is_unique_expr(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").is_unique(), "index").sort("index") expected = {"a": [False, False, True], "b": [True, True, True], "index": [0, 1, 2]} assert_equal_data(result, expected) def test_is_unique_expr_grouped( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(constructor) for x in ("pandas", "dask", "modin", "cudf", "pyarrow")): + if any( + x in str(nw_frame_constructor) + for x in ("pandas", "dask", "modin", "cudf", "pyarrow") + ): # non-trivial aggregation request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 4, 4], "b": [1, 1, 1, 2, 2], "index": [0, 1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").is_unique().over("b"), "index").sort("index") expected = {"a": [False, False, True, False, False], "index": [0, 1, 2, 3, 4]} assert_equal_data(result, expected) -def test_is_unique_w_nulls_expr(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_is_unique_w_nulls_expr(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, 1, 2], "b": [None, 2, None], "index": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").is_unique(), "index").sort("index") expected = {"a": [True, True, True], "b": [False, True, False], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_unique_series(constructor_eager: ConstructorEager) -> None: +def test_is_unique_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.is_unique() expected = {"a": [False, False, True]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/kurtosis_test.py b/tests/expr_and_series/kurtosis_test.py index 55727445fe..b4e4890a67 100644 --- a/tests/expr_and_series/kurtosis_test.py +++ b/tests/expr_and_series/kurtosis_test.py @@ -17,9 +17,9 @@ ], ) def test_kurtosis_series( - constructor_eager: ConstructorEager, data: list[float], expected: float | None + nw_eager_constructor: ConstructorEager, data: list[float], expected: float | None ) -> None: - result = nw.from_native(constructor_eager({"a": data}), eager_only=True)[ + result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ "a" ].kurtosis() assert_equal_data({"a": [result]}, {"a": [expected]}) @@ -38,18 +38,20 @@ def test_kurtosis_series( ) @pytest.mark.filterwarnings("ignore:.*invalid value:RuntimeWarning:dask") def test_kurtosis_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, data: list[float], expected: float | None, request: pytest.FixtureRequest, ) -> None: - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): # https://github.com/ibis-project/ibis/issues/11341 request.applymarker(pytest.mark.xfail) - if "pyspark" in str(constructor) and int(request.node.callspec.id[-1]) == 0: + if "pyspark" in str(nw_frame_constructor) and int(request.node.callspec.id[-1]) == 0: # Can not infer schema from empty dataset. pytest.skip() - result = nw.from_native(constructor({"a": data})).select(nw.col("a").kurtosis()) + result = nw.from_native(nw_frame_constructor({"a": data})).select( + nw.col("a").kurtosis() + ) assert_equal_data(result, {"a": [expected]}) diff --git a/tests/expr_and_series/len_test.py b/tests/expr_and_series/len_test.py index 755c389a28..684cfae24c 100644 --- a/tests/expr_and_series/len_test.py +++ b/tests/expr_and_series/len_test.py @@ -4,10 +4,10 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_len_no_filter(constructor: Constructor) -> None: +def test_len_no_filter(nw_frame_constructor: Constructor) -> None: data = {"a": list("xyz"), "b": [1, 2, None]} expected = {"l": [3], "l2": [6], "l3": [3]} - df = nw.from_native(constructor(data)).select( + df = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").len().alias("l"), (nw.col("a").len() * 2).alias("l2"), nw.col("b").len().alias("l3"), @@ -16,10 +16,10 @@ def test_len_no_filter(constructor: Constructor) -> None: assert_equal_data(df, expected) -def test_len_chaining(constructor_eager: ConstructorEager) -> None: +def test_len_chaining(nw_eager_constructor: ConstructorEager) -> None: data = {"a": list("xyz"), "b": [1, 2, 1]} expected = {"a1": [2], "a2": [1]} - df = nw.from_native(constructor_eager(data)).select( + df = nw.from_native(nw_eager_constructor(data)).select( nw.col("a").filter(nw.col("b") == 1).len().alias("a1"), nw.col("a").filter(nw.col("b") == 2).len().alias("a2"), ) @@ -27,14 +27,14 @@ def test_len_chaining(constructor_eager: ConstructorEager) -> None: assert_equal_data(df, expected) -def test_namespace_len(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).select( +def test_namespace_len(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).select( nw.len(), a=nw.len() ) expected = {"len": [3], "a": [3]} assert_equal_data(df, expected) df = ( - nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .filter(nw.col("a") < 0) .select(nw.len(), a=nw.len()) ) @@ -42,9 +42,9 @@ def test_namespace_len(constructor: Constructor) -> None: assert_equal_data(df, expected) -def test_len_series(constructor_eager: ConstructorEager) -> None: +def test_len_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 1]} - s = nw.from_native(constructor_eager(data), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] assert s.len() == 3 assert len(s) == 3 diff --git a/tests/expr_and_series/list/contains_test.py b/tests/expr_and_series/list/contains_test.py index 6e56846d6e..edcad40861 100644 --- a/tests/expr_and_series/list/contains_test.py +++ b/tests/expr_and_series/list/contains_test.py @@ -14,26 +14,28 @@ expected = {"a": [True, None, False]} -def test_contains_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: +def test_contains_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("dask", "modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.contains(2) ) assert_equal_data(result, expected) def test_contains_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: if any( - backend in str(constructor_eager) + backend in str(nw_eager_constructor) for backend in ("modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.contains(2) assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/list/get_test.py b/tests/expr_and_series/list/get_test.py index 338ab6197a..713f5d67b6 100644 --- a/tests/expr_and_series/list/get_test.py +++ b/tests/expr_and_series/list/get_test.py @@ -13,17 +13,20 @@ @pytest.mark.parametrize(("index", "expected"), [(0, {"a": [1, None, None, None]})]) def test_get_expr( - request: pytest.FixtureRequest, constructor: Constructor, index: int, expected: Any + request: pytest.FixtureRequest, + nw_frame_constructor: Constructor, + index: int, + expected: Any, ) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.get(index) ) @@ -33,43 +36,43 @@ def test_get_expr( @pytest.mark.parametrize(("index", "expected"), [(0, {"a": [1, None, None, None]})]) def test_get_series( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, index: int, expected: Any, ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if str(constructor_eager).startswith("pandas") and "pyarrow" not in str( - constructor_eager + if str(nw_eager_constructor).startswith("pandas") and "pyarrow" not in str( + nw_eager_constructor ): - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) msg = re.escape("Series must be of PyArrow List type to support list namespace.") with pytest.raises(TypeError, match=msg): df["a"].list.get(index) return - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.get(index) assert_equal_data({"a": result}, expected) -def test_get_expr_negative_index(constructor: Constructor) -> None: +def test_get_expr_negative_index(nw_frame_constructor: Constructor) -> None: data = {"a": [[1, 2], [None, 3], [None], None]} index = -1 - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) msg = re.escape( f"Index {index} is out of bounds: should be greater than or equal to 0." ) @@ -77,16 +80,16 @@ def test_get_expr_negative_index(constructor: Constructor) -> None: df.select(nw.col("a").cast(nw.List(nw.Int32())).list.get(index)) -def test_get_series_negative_index(constructor_eager: ConstructorEager) -> None: +def test_get_series_negative_index(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [[1, 2], [None, 3], [None], None]} index = -1 - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) msg = re.escape( f"Index {index} is out of bounds: should be greater than or equal to 0." ) @@ -94,16 +97,16 @@ def test_get_series_negative_index(constructor_eager: ConstructorEager) -> None: df["a"].list.get(index) -def test_get_expr_non_int_index(constructor: Constructor) -> None: +def test_get_expr_non_int_index(nw_frame_constructor: Constructor) -> None: data = {"a": [[1, 2], [None, 3], [None], None], "index": [0, 1, 0, 0]} index = "index" - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) msg = re.escape( f"Index must be of type 'int'. Got type '{type(index).__name__}' instead." ) @@ -111,16 +114,16 @@ def test_get_expr_non_int_index(constructor: Constructor) -> None: df.select(nw.col("a").cast(nw.List(nw.Int32())).list.get(index)) # type: ignore[arg-type] -def test_get_series_non_int_index(constructor_eager: ConstructorEager) -> None: +def test_get_series_non_int_index(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [[1, 2], [None, 3], [None], None], "index": [0, 1, 0, 0]} index = "index" - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) msg = re.escape( f"Index must be of type 'int'. Got type '{type(index).__name__}' instead." ) diff --git a/tests/expr_and_series/list/len_test.py b/tests/expr_and_series/list/len_test.py index 918fda5831..46598af7e4 100644 --- a/tests/expr_and_series/list/len_test.py +++ b/tests/expr_and_series/list/len_test.py @@ -9,16 +9,18 @@ expected = {"a": [2, 3, None, 0, 1]} -def test_len_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_len_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.len() ) @@ -26,17 +28,17 @@ def test_len_expr(request: pytest.FixtureRequest, constructor: Constructor) -> N def test_len_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.len() assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/list/max_test.py b/tests/expr_and_series/list/max_test.py index 646bff2244..60adc6f40c 100644 --- a/tests/expr_and_series/list/max_test.py +++ b/tests/expr_and_series/list/max_test.py @@ -14,28 +14,30 @@ expected = [4, -1, None, None, None] -def test_max_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_max_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.max() ) assert_equal_data(result, {"a": expected}) def test_max_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(backend in str(constructor_eager) for backend in ("cudf",)): + if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.max() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/mean_test.py b/tests/expr_and_series/list/mean_test.py index 9175d5b248..b4711bc846 100644 --- a/tests/expr_and_series/list/mean_test.py +++ b/tests/expr_and_series/list/mean_test.py @@ -14,28 +14,30 @@ expected = [2.75, -1, None, None, None] -def test_mean_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_mean_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.mean() ) assert_equal_data(result, {"a": expected}) def test_mean_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(backend in str(constructor_eager) for backend in ("cudf",)): + if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.mean() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/median_test.py b/tests/expr_and_series/list/median_test.py index f0d3c615ff..ae56095115 100644 --- a/tests/expr_and_series/list/median_test.py +++ b/tests/expr_and_series/list/median_test.py @@ -16,28 +16,30 @@ expected_pyarrow = [2.5, -1, None, None, None, 3] -def test_median_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf", "ibis")) or ( - "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7) - ): +def test_median_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any( + backend in str(nw_frame_constructor) for backend in ("dask", "cudf", "ibis") + ) or ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7)): # ibis issue: https://github.com/ibis-project/ibis/issues/11788 request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") if ( - any(backend in str(constructor) for backend in ("pandas", "pyarrow")) + any(backend in str(nw_frame_constructor) for backend in ("pandas", "pyarrow")) and sys.version_info < (3, 10) and is_windows() ): # pragma: no cover reason = "The issue only affects old Python versions on Windows." request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.median() ) if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("pandas", "pyarrow", "pandas[pyarrow]") ): # there is a mismatch as pyarrow uses an approximate median @@ -47,27 +49,27 @@ def test_median_expr(request: pytest.FixtureRequest, constructor: Constructor) - def test_median_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(backend in str(constructor_eager) for backend in ("cudf",)) or ( - "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7) + if any(backend in str(nw_eager_constructor) for backend in ("cudf",)) or ( + "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7) ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") if ( - any(backend in str(constructor_eager) for backend in ("pandas", "pyarrow")) + any(backend in str(nw_eager_constructor) for backend in ("pandas", "pyarrow")) and sys.version_info < (3, 10) and is_windows() ): # pragma: no cover reason = "The issue only affects old Python versions on Windows." request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.median() if any( - backend in str(constructor_eager) + backend in str(nw_eager_constructor) for backend in ("pandas", "pyarrow", "pandas[pyarrow]") ): # there is a mismatch as pyarrow uses an approximate median diff --git a/tests/expr_and_series/list/min_test.py b/tests/expr_and_series/list/min_test.py index 2039f7de56..9995d9e553 100644 --- a/tests/expr_and_series/list/min_test.py +++ b/tests/expr_and_series/list/min_test.py @@ -14,28 +14,30 @@ expected = [2, -1, None, None, None] -def test_min_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_min_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.min() ) assert_equal_data(result, {"a": expected}) def test_min_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(backend in str(constructor_eager) for backend in ("cudf",)): + if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.min().to_list() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/sort_test.py b/tests/expr_and_series/list/sort_test.py index 1866934a73..2df250bc1b 100644 --- a/tests/expr_and_series/list/sort_test.py +++ b/tests/expr_and_series/list/sort_test.py @@ -55,23 +55,23 @@ ) def test_sort_expr_args( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, descending: bool, # noqa: FBT001 nulls_last: bool, # noqa: FBT001 expected: list[Any], ) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "ibis" in str(constructor) and descending: + if "ibis" in str(nw_frame_constructor) and descending: # https://github.com/ibis-project/ibis/issues/11735 request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 5): pytest.skip() - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a") .cast(nw.List(nw.Int32())) .list.sort(descending=descending, nulls_last=nulls_last) @@ -90,20 +90,20 @@ def test_sort_expr_args( ) def test_sort_series_args( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, descending: bool, # noqa: FBT001 nulls_last: bool, # noqa: FBT001 expected: list[Any], ) -> None: - if any(backend in str(constructor_eager) for backend in ("dask", "cudf")): + if any(backend in str(nw_eager_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 5): pytest.skip() - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = ( df["a"] .cast(nw.List(nw.Int32())) diff --git a/tests/expr_and_series/list/sum_test.py b/tests/expr_and_series/list/sum_test.py index d66266e016..b96b922e07 100644 --- a/tests/expr_and_series/list/sum_test.py +++ b/tests/expr_and_series/list/sum_test.py @@ -14,31 +14,33 @@ expected = [11, -1, None, 0, 0] -def test_sum_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf")): +def test_sum_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 2): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 2): reason = "version too old, duckdb 1.2 required for LambdaExpression." pytest.skip(reason=reason) - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.sum() ) assert_equal_data(result, {"a": expected}) def test_sum_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(backend in str(constructor_eager) for backend in ("cudf",)): + if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.sum() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/unique_test.py b/tests/expr_and_series/list/unique_test.py index 3d7c9dd039..d9dad08d1b 100644 --- a/tests/expr_and_series/list/unique_test.py +++ b/tests/expr_and_series/list/unique_test.py @@ -14,16 +14,18 @@ expected = {2, 3, None} -def test_unique_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: +def test_unique_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("dask", "modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .select(nw.col("a").cast(nw.List(nw.Int32())).list.unique()) .lazy() .collect()["a"] @@ -41,14 +43,14 @@ def test_unique_expr(request: pytest.FixtureRequest, constructor: Constructor) - def test_unique_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: if any( - backend in str(constructor_eager) + backend in str(nw_eager_constructor) for backend in ("modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.unique().to_list() assert len(result) == 4 assert len(result[0]) == 3 diff --git a/tests/expr_and_series/lit_test.py b/tests/expr_and_series/lit_test.py index 188292c0d1..0ba06f9960 100644 --- a/tests/expr_and_series/lit_test.py +++ b/tests/expr_and_series/lit_test.py @@ -26,22 +26,22 @@ [(None, [2, 2, 2]), (nw.String, ["2", "2", "2"]), (nw.Float32, [2.0, 2.0, 2.0])], ) def test_lit( - constructor: Constructor, dtype: DType | None, expected_lit: list[Any] + nw_frame_constructor: Constructor, dtype: DType | None, expected_lit: list[Any] ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(nw.lit(2, dtype).alias("lit")) expected = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "lit": expected_lit} assert_equal_data(result, expected) -def test_lit_error(constructor: Constructor) -> None: +def test_lit_error(nw_frame_constructor: Constructor) -> None: pytest.importorskip("numpy") import numpy as np data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw).lazy() with pytest.raises( ValueError, match="numpy arrays are not supported as literal values" @@ -49,9 +49,9 @@ def test_lit_error(constructor: Constructor) -> None: _ = df.with_columns(nw.lit(np.array([1, 2])).alias("lit")) # pyright: ignore[reportArgumentType] -def test_lit_out_name(constructor: Constructor) -> None: +def test_lit_out_name(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(nw.lit(2)) expected = {"a": [1, 3, 2], "literal": [2, 2, 2]} @@ -74,17 +74,20 @@ def test_lit_out_name(constructor: Constructor) -> None: ], ) def test_lit_operation_in_select( - constructor: Constructor, col_name: str, expr: nw.Expr, expected_result: list[int] + nw_frame_constructor: Constructor, + col_name: str, + expr: nw.Expr, + expected_result: list[int], ) -> None: if ( - "dask" in str(constructor) + "dask" in str(nw_frame_constructor) and col_name == "right_lit_with_abs" and DASK_VERSION < (2025,) ): pytest.skip() data = {"a": [1, 3, 2]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw).lazy() result = df.select(expr.alias(col_name)) expected = {col_name: expected_result} @@ -99,10 +102,13 @@ def test_lit_operation_in_select( ], ) def test_lit_operation_in_with_columns( - constructor: Constructor, col_name: str, expr: nw.Expr, expected_result: list[int] + nw_frame_constructor: Constructor, + col_name: str, + expr: nw.Expr, + expected_result: list[int], ) -> None: data = {"a": [1, 3, 2]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(expr.alias(col_name)) expected = {"a": data["a"], col_name: expected_result} @@ -110,16 +116,18 @@ def test_lit_operation_in_with_columns( @pytest.mark.skipif(PANDAS_VERSION < (1, 5), reason="too old for pyarrow") -def test_date_lit(constructor: Constructor, request: pytest.FixtureRequest) -> None: +def test_date_lit( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: # https://github.com/dask/dask/issues/11637 - if "dask" in str(constructor) or ( + if "dask" in str(nw_frame_constructor) or ( # https://github.com/rapidsai/cudf/pull/18832 - "cudf" in str(constructor) and CUDF_VERSION >= (25, 8, 0) + "cudf" in str(nw_frame_constructor) and CUDF_VERSION >= (25, 8, 0) ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): pytest.importorskip("pyarrow") - df = nw.from_native(constructor({"a": [1]})) + df = nw.from_native(nw_frame_constructor({"a": [1]})) result = df.with_columns(nw.lit(date(2020, 1, 1), dtype=nw.Date)).collect_schema() if df.implementation.is_cudf(): # cudf has no date dtype @@ -163,30 +171,32 @@ def test_pyarrow_lit_string() -> None: ) def test_nested_structures( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, value: PythonLiteral, dtype: IntoDType | None, ) -> None: is_empty_dict = isinstance(value, dict) and len(value) == 0 non_pyspark_sql_like = ("duckdb", "sqlframe", "ibis") - is_non_pyspark_sql_like = any(x in str(constructor) for x in non_pyspark_sql_like) + is_non_pyspark_sql_like = any( + x in str(nw_frame_constructor) for x in non_pyspark_sql_like + ) if is_non_pyspark_sql_like and is_empty_dict: reason = "Cannot create an empty struct type for backend" request.applymarker(pytest.mark.xfail(reason=reason, raises=NotImplementedError)) # TODO(FBruzzesi): Check cudf - if any(x in str(constructor) for x in ("cudf", "dask")): + if any(x in str(nw_frame_constructor) for x in ("cudf", "dask")): reason = "Nested structures are not support for backend" request.applymarker(pytest.mark.xfail(reason=reason, raises=NotImplementedError)) - if any(x in str(constructor) for x in ("pandas", "modin")) and ( + if any(x in str(nw_frame_constructor) for x in ("pandas", "modin")) and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 0) ): # pragma: no cover reason = "Requires pyarrow and pandas 2.0+" pytest.skip(reason=reason) if ( - "polars" in str(constructor) + "polars" in str(nw_frame_constructor) and isinstance(value, dict) and POLARS_VERSION < (1, 10, 0) ): # pragma: no cover @@ -200,7 +210,7 @@ def test_nested_structures( value_ = list(value) if isinstance(value, tuple) else value expected_nested = {"nested": [value_] * size} - frame = nw.from_native(constructor(data)) + frame = nw.from_native(nw_frame_constructor(data)) result_with_cols = frame.with_columns(expr) assert_equal_data(result_with_cols, {**data, **expected_nested}) diff --git a/tests/expr_and_series/log_test.py b/tests/expr_and_series/log_test.py index 4157b5a4a6..ac5300d289 100644 --- a/tests/expr_and_series/log_test.py +++ b/tests/expr_and_series/log_test.py @@ -18,16 +18,16 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") @pytest.mark.parametrize("base", [2, 10, math.e]) -def test_log_expr(constructor: Constructor, base: float) -> None: - df = nw.from_native(constructor(data)) +def test_log_expr(nw_frame_constructor: Constructor, base: float) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").log(base=base)) assert_equal_data(result, {"a": expected[base]}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") @pytest.mark.parametrize("base", [2, 10, math.e]) -def test_log_series(constructor_eager: ConstructorEager, base: float) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_log_series(nw_eager_constructor: ConstructorEager, base: float) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.log(base=base) assert_equal_data({"a": result}, {"a": expected[base]}) diff --git a/tests/expr_and_series/map_batches_test.py b/tests/expr_and_series/map_batches_test.py index d6f8cc8b32..8798131cba 100644 --- a/tests/expr_and_series/map_batches_test.py +++ b/tests/expr_and_series/map_batches_test.py @@ -20,8 +20,8 @@ data = {"a": [1, 2, 3], "b": [4, 5, 6], "z": [7.0, 8.0, 9.0]} -def test_map_batches_expr_compliant(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_map_batches_expr_compliant(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) expected = df.select(nw.col("a", "b").map_batches(lambda s: s + 1).name.suffix("1")) assert_equal_data(expected, {"a1": [2, 3, 4], "b1": [5, 6, 7]}) @@ -31,9 +31,9 @@ def test_map_batches_expr_compliant(constructor_eager: ConstructorEager) -> None [(1, nw.Int64()), ("foo", nw.String()), ([1, 2], nw.List(nw.Int64()))], ) def test_map_batches_expr_scalar( - constructor_eager: ConstructorEager, value: Any, dtype: DType + nw_eager_constructor: ConstructorEager, value: Any, dtype: DType ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) if dtype.is_nested() and df.implementation.is_pandas_like(): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "pandas is too old for nested types" @@ -48,8 +48,8 @@ def test_map_batches_expr_scalar( assert_equal_data(expected, {"a": [value], "b": [value]}) -def test_map_batches_expr_numpy_array(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_map_batches_expr_numpy_array(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) expected = df.select( nw.col("a") .map_batches(lambda s: s.to_numpy() + 1, return_dtype=nw.Float64()) @@ -58,8 +58,8 @@ def test_map_batches_expr_numpy_array(constructor_eager: ConstructorEager) -> No assert_equal_data(expected, {"a": [9.0]}) -def test_map_batches_expr_numpy_scalar(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_map_batches_expr_numpy_scalar(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) expected = df.select( nw.all().map_batches(lambda s: s.to_numpy().argmax(), returns_scalar=True) @@ -67,19 +67,19 @@ def test_map_batches_expr_numpy_scalar(constructor_eager: ConstructorEager) -> N assert_equal_data(expected, {"a": [2], "b": [2], "z": [2]}) -def test_map_batches_expr_names(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_map_batches_expr_names(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) expected = nw.from_native(df.select(nw.all().map_batches(lambda x: x.to_numpy()))) assert_equal_data(expected, {"a": [1, 2, 3], "b": [4, 5, 6], "z": [7.0, 8.0, 9.0]}) def test_map_batches_exception( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 32, 3): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 32, 3): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) msg = ( r"`map(?:_batches)?` with `returns_scalar=False` must return a Series; found " r"'numpy\.int(?:32|64)'\." diff --git a/tests/expr_and_series/max_horizontal_test.py b/tests/expr_and_series/max_horizontal_test.py index cc0bddfb1a..f435ce5611 100644 --- a/tests/expr_and_series/max_horizontal_test.py +++ b/tests/expr_and_series/max_horizontal_test.py @@ -10,16 +10,16 @@ @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_maxh(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_maxh(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(horizontal_max=nw.max_horizontal("a", nw.col("b"), "z")) expected = {"horizontal_max": expected_values} assert_equal_data(result, expected) @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_maxh_all(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_maxh_all(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.max_horizontal(nw.all()), c=nw.max_horizontal(nw.all())) expected = {"a": expected_values, "c": expected_values} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/max_test.py b/tests/expr_and_series/max_test.py index eb359121c6..ce58eddc2b 100644 --- a/tests/expr_and_series/max_test.py +++ b/tests/expr_and_series/max_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").max(), nw.max("a", "b", "z")]) -def test_expr_max_expr(constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(constructor(data)) +def test_expr_max_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(expr) expected = {"a": [3], "b": [6], "z": [9.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_max_expr(constructor: Constructor, expr: nw.Expr) -> None: @pytest.mark.parametrize(("col", "expected"), [("a", 3), ("b", 6), ("z", 9.0)]) def test_expr_max_series( - constructor_eager: ConstructorEager, col: str, expected: float + nw_eager_constructor: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.max() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/mean_horizontal_test.py b/tests/expr_and_series/mean_horizontal_test.py index bc5bc12fa6..a87ed4df99 100644 --- a/tests/expr_and_series/mean_horizontal_test.py +++ b/tests/expr_and_series/mean_horizontal_test.py @@ -6,29 +6,29 @@ from tests.utils import Constructor, assert_equal_data -def test_meanh(constructor: Constructor) -> None: +def test_meanh(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, None, None], "b": [4, None, 6, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(horizontal_mean=nw.mean_horizontal(nw.col("a"), nw.col("b"))) expected = {"horizontal_mean": [2.5, 3.0, 6.0, None]} assert_equal_data(result, expected) def test_meanh_with_literal( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, None, None], "b": [4, None, 6, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(horizontal_mean=nw.mean_horizontal(nw.lit(1), "a", nw.col("b"))) expected = {"horizontal_mean": [2.0, 2.0, 3.5, 1.0]} assert_equal_data(result, expected) -def test_meanh_all(constructor: Constructor) -> None: +def test_meanh_all(nw_frame_constructor: Constructor) -> None: data = {"a": [2, 4, 6], "b": [10, 20, 30]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.mean_horizontal(nw.all())) expected = {"a": [6, 12, 18]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/mean_test.py b/tests/expr_and_series/mean_test.py index 39a97bd53a..a0b19583a3 100644 --- a/tests/expr_and_series/mean_test.py +++ b/tests/expr_and_series/mean_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").mean(), nw.mean("a", "b", "z")]) -def test_expr_mean_expr(constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(constructor(data)) +def test_expr_mean_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(expr) expected = {"a": [2.0], "b": [5.0], "z": [8.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_mean_expr(constructor: Constructor, expr: nw.Expr) -> None: @pytest.mark.parametrize(("col", "expected"), [("a", 2.0), ("b", 5.0), ("z", 8.0)]) def test_expr_mean_series( - constructor_eager: ConstructorEager, col: str, expected: float + nw_eager_constructor: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.mean() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/median_test.py b/tests/expr_and_series/median_test.py index b01350586a..356397d640 100644 --- a/tests/expr_and_series/median_test.py +++ b/tests/expr_and_series/median_test.py @@ -20,11 +20,11 @@ "expr", [nw.col("a", "b", "z").median(), nw.median("a", "b", "z")] ) def test_median_expr( - constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest ) -> None: - if "dask_lazy_p2" in str(constructor): + if "dask_lazy_p2" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(expr) expected = {"a": [3.0], "b": [5.0], "z": [8.0]} assert_equal_data(result, expected) @@ -32,25 +32,25 @@ def test_median_expr( @pytest.mark.parametrize(("col", "expected"), [("a", 3.0), ("b", 5.0), ("z", 8.0)]) def test_median_series( - constructor_eager: ConstructorEager, col: str, expected: float + nw_eager_constructor: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.median() assert_equal_data({col: [result]}, {col: [expected]}) @pytest.mark.parametrize("expr", [nw.col("s").median(), nw.median("s")]) def test_median_expr_raises_on_str( - constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest ) -> None: if ( - ("pyspark" in str(constructor)) - or "duckdb" in str(constructor) - or "ibis" in str(constructor) + ("pyspark" in str(nw_frame_constructor)) + or "duckdb" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) if isinstance(df, nw.LazyFrame): with pytest.raises( InvalidOperationError, match="`median` operation not supported" @@ -65,9 +65,9 @@ def test_median_expr_raises_on_str( @pytest.mark.parametrize(("col"), [("s")]) def test_median_series_raises_on_str( - constructor_eager: ConstructorEager, col: str + nw_eager_constructor: ConstructorEager, col: str ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] with pytest.raises( InvalidOperationError, match=re.escape("`median` operation not supported for non-numeric input type."), diff --git a/tests/expr_and_series/min_horizontal_test.py b/tests/expr_and_series/min_horizontal_test.py index df9ff31feb..f91bf1338f 100644 --- a/tests/expr_and_series/min_horizontal_test.py +++ b/tests/expr_and_series/min_horizontal_test.py @@ -10,16 +10,16 @@ @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_minh(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_minh(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(horizontal_min=nw.min_horizontal("a", nw.col("b"), "z")) expected = {"horizontal_min": expected_values} assert_equal_data(result, expected) @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_minh_all(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_minh_all(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.min_horizontal(nw.all()), c=nw.min_horizontal(nw.all())) expected = {"a": expected_values, "c": expected_values} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/min_test.py b/tests/expr_and_series/min_test.py index 842e70c166..c8f0409da5 100644 --- a/tests/expr_and_series/min_test.py +++ b/tests/expr_and_series/min_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").min(), nw.min("a", "b", "z")]) -def test_expr_min_expr(constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(constructor(data)) +def test_expr_min_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(expr) expected = {"a": [1], "b": [4], "z": [7.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_min_expr(constructor: Constructor, expr: nw.Expr) -> None: @pytest.mark.parametrize(("col", "expected"), [("a", 1), ("b", 4), ("z", 7.0)]) def test_expr_min_series( - constructor_eager: ConstructorEager, col: str, expected: float + nw_eager_constructor: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.min() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/mode_test.py b/tests/expr_and_series/mode_test.py index a17de7bd17..2df3dcf900 100644 --- a/tests/expr_and_series/mode_test.py +++ b/tests/expr_and_series/mode_test.py @@ -19,22 +19,22 @@ } -def test_mode_single_expr_keep_all(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_mode_single_expr_keep_all(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").mode(keep="all")).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series_keep_all(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_mode_series_keep_all(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.mode(keep="all").sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_series_keep_any(constructor_eager: ConstructorEager) -> None: - frame = nw.from_native(constructor_eager(data), eager_only=True) +def test_mode_series_keep_any(nw_eager_constructor: ConstructorEager) -> None: + frame = nw.from_native(nw_eager_constructor(data), eager_only=True) result_a = frame["a"].mode(keep="any") assert result_a in {1, 2} @@ -42,16 +42,16 @@ def test_mode_series_keep_any(constructor_eager: ConstructorEager) -> None: assert result_b == 3 -def test_mode_different_lengths_keep_all(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths_keep_all(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) with pytest.raises(ShapeError): df.select(nw.col("a", "b").mode(keep="all")) -def test_mode_expr_keep_any(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_mode_expr_keep_any(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").mode(keep="any")).lazy().collect() try: @@ -62,8 +62,8 @@ def test_mode_expr_keep_any(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_mode_expr_keep_all_lazy(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_mode_expr_keep_all_lazy(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) impl = df.implementation not_implemented = { nw.Implementation.DUCKDB, @@ -85,9 +85,9 @@ def test_mode_expr_keep_all_lazy(constructor: Constructor) -> None: def test_mode_group_by_unimodal( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - df = nw.from_native(constructor(data_group)) + df = nw.from_native(nw_frame_constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): @@ -115,13 +115,13 @@ def test_mode_group_by_unimodal( ], ) def test_mode_group_by_multimodal( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, mode_col: str, expected_opt_1: list[Any], expected_opt_2: list[Any], ) -> None: - df = nw.from_native(constructor(data_group)) + df = nw.from_native(nw_frame_constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): @@ -156,11 +156,11 @@ def test_mode_group_by_multimodal( ], ) def test_mode_group_by_multiple_cols( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, mode_expr: nw.Expr | list[nw.Expr], ) -> None: - df = nw.from_native(constructor(data_group)) + df = nw.from_native(nw_frame_constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): diff --git a/tests/expr_and_series/n_unique_test.py b/tests/expr_and_series/n_unique_test.py index e9af1f0154..8ac6ae25ea 100644 --- a/tests/expr_and_series/n_unique_test.py +++ b/tests/expr_and_series/n_unique_test.py @@ -8,31 +8,35 @@ data = {"a": [1.0, None, None, 3.0], "b": [1.0, None, 4.0, 5.0]} -def test_n_unique(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_n_unique(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.all().n_unique()) expected = {"a": [3], "b": [4]} assert_equal_data(result, expected) -def test_n_unique_over(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_n_unique_over( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/10550 request.applymarker(pytest.mark.xfail) - if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): + if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( + nw_frame_constructor + ): # "Distinct window functions are not supported" request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): reason = "NotImplementedError: Passing kwargs to func is currently not supported." request.applymarker(pytest.mark.xfail(reason=reason)) data = {"a": [1, None, None, 1, 2, 2, 2, None, 3], "b": [1, 1, 1, 1, 1, 1, 1, 2, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns( nw.all().n_unique(), a_over_b=nw.col("a").n_unique().over("b") ).sort("a_over_b") @@ -40,8 +44,8 @@ def test_n_unique_over(constructor: Constructor, request: pytest.FixtureRequest) assert_equal_data(result, expected) -def test_n_unique_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_n_unique_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = {"a": [3], "b": [4]} result_series = {"a": [df["a"].n_unique()], "b": [df["b"].n_unique()]} assert_equal_data(result_series, expected) diff --git a/tests/expr_and_series/name/keep_test.py b/tests/expr_and_series/name/keep_test.py index e4a3ba17f6..aaeb68de44 100644 --- a/tests/expr_and_series/name/keep_test.py +++ b/tests/expr_and_series/name/keep_test.py @@ -6,22 +6,22 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_keep(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_keep(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.keep()) expected = {k: [e * 2 for e in v] for k, v in data.items()} assert_equal_data(result, expected) -def test_keep_after_alias(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_keep_after_alias(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.keep()) expected = {"foo": data["foo"]} assert_equal_data(result, expected) -def test_keep_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_keep_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select("foo").select(nw.all().alias("fdfsad").name.keep()) expected = {"foo": [1, 2, 3]} diff --git a/tests/expr_and_series/name/map_test.py b/tests/expr_and_series/name/map_test.py index eb4b2bc22b..2a7e420433 100644 --- a/tests/expr_and_series/name/map_test.py +++ b/tests/expr_and_series/name/map_test.py @@ -12,24 +12,24 @@ def map_func(s: str | None) -> str: return str(s)[::-1].lower() -def test_map(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_map(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.map(function=map_func)) expected = {"oof": [2, 4, 6], "rab": [8, 10, 12]} assert_equal_data(result, expected) -def test_map_after_alias(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_map_after_alias(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.map(function=map_func)) expected = {"oof_rof_saila": data["foo"]} assert_equal_data(result, expected) -def test_map_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_map_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.map(function=map_func)) expected = {"oof": [1, 2, 3], "rab": [4, 5, 6]} diff --git a/tests/expr_and_series/name/prefix_test.py b/tests/expr_and_series/name/prefix_test.py index a639455823..d775eb681c 100644 --- a/tests/expr_and_series/name/prefix_test.py +++ b/tests/expr_and_series/name/prefix_test.py @@ -9,24 +9,24 @@ prefix = "with_prefix_" -def test_prefix(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_prefix(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.prefix(prefix)) expected = {"with_prefix_foo": [2, 4, 6], "with_prefix_BAR": [8, 10, 12]} assert_equal_data(result, expected) -def test_suffix_after_alias(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_suffix_after_alias(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.prefix(prefix)) expected = {"with_prefix_alias_for_foo": [1, 2, 3]} assert_equal_data(result, expected) -def test_prefix_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_prefix_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.prefix(prefix)) expected = {"with_prefix_foo": [1, 2, 3], "with_prefix_BAR": [4, 5, 6]} diff --git a/tests/expr_and_series/name/suffix_test.py b/tests/expr_and_series/name/suffix_test.py index 437d93e05a..67b26bff6d 100644 --- a/tests/expr_and_series/name/suffix_test.py +++ b/tests/expr_and_series/name/suffix_test.py @@ -9,17 +9,17 @@ suffix = "_with_suffix" -def test_suffix(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_suffix(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.suffix(suffix)) expected = {"foo_with_suffix": [2, 4, 6], "BAR_with_suffix": [8, 10, 12]} assert_equal_data(result, expected) -def test_suffix_after_alias(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_suffix_after_alias(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.suffix(suffix)) expected = {"alias_for_foo_with_suffix": [1, 2, 3]} assert_equal_data(result, expected) @@ -30,8 +30,8 @@ def test_suffix_after_alias(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_suffix_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_suffix_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.suffix(suffix)) expected = {"foo_with_suffix": [1, 2, 3], "BAR_with_suffix": [4, 5, 6]} diff --git a/tests/expr_and_series/name/to_lowercase_test.py b/tests/expr_and_series/name/to_lowercase_test.py index 41a88a4f9c..b586a34e06 100644 --- a/tests/expr_and_series/name/to_lowercase_test.py +++ b/tests/expr_and_series/name/to_lowercase_test.py @@ -8,24 +8,24 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_to_lowercase(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_to_lowercase(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.to_lowercase()) expected = {"foo": [2, 4, 6], "bar": [8, 10, 12]} assert_equal_data(result, expected) -def test_to_lowercase_after_alias(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_to_lowercase_after_alias(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("BAR")).alias("ALIAS_FOR_BAR").name.to_lowercase()) expected = {"alias_for_bar": [4, 5, 6]} assert_equal_data(result, expected) -def test_to_lowercase_raise_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_to_lowercase_raise_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.to_lowercase()) expected = {"foo": [1, 2, 3], "bar": [4, 5, 6]} diff --git a/tests/expr_and_series/name/to_uppercase_test.py b/tests/expr_and_series/name/to_uppercase_test.py index 9204ac86b5..441ddcc992 100644 --- a/tests/expr_and_series/name/to_uppercase_test.py +++ b/tests/expr_and_series/name/to_uppercase_test.py @@ -8,24 +8,24 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_to_uppercase(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_to_uppercase(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.to_uppercase()) expected = {"FOO": [2, 4, 6], "BAR": [8, 10, 12]} assert_equal_data(result, expected) -def test_to_uppercase_after_alias(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_to_uppercase_after_alias(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.to_uppercase()) expected = {"ALIAS_FOR_FOO": [1, 2, 3]} assert_equal_data(result, expected) -def test_to_uppercase_anonymous(constructor: Constructor) -> None: - df_raw = constructor(data) +def test_to_uppercase_anonymous(nw_frame_constructor: Constructor) -> None: + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.to_uppercase()) expected = {"FOO": [1, 2, 3], "BAR": [4, 5, 6]} diff --git a/tests/expr_and_series/nth_test.py b/tests/expr_and_series/nth_test.py index 86f9bfe2eb..0ec1fe52c7 100644 --- a/tests/expr_and_series/nth_test.py +++ b/tests/expr_and_series/nth_test.py @@ -20,11 +20,13 @@ ], ) def test_nth( - constructor: Constructor, idx: int | list[int], expected: dict[str, list[int]] + nw_frame_constructor: Constructor, + idx: int | list[int], + expected: dict[str, list[int]], ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.nth(idx)) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/null_count_test.py b/tests/expr_and_series/null_count_test.py index 6efef0ada1..6e554ce00e 100644 --- a/tests/expr_and_series/null_count_test.py +++ b/tests/expr_and_series/null_count_test.py @@ -6,15 +6,15 @@ data = {"a": [1.0, None, None, 3.0], "b": [1.0, None, 4.0, 5.0]} -def test_null_count_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_null_count_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a", "b").null_count()) expected = {"a": [2], "b": [1]} assert_equal_data(result, expected) -def test_null_count_series(constructor_eager: ConstructorEager) -> None: +def test_null_count_series(nw_eager_constructor: ConstructorEager) -> None: data = [1, 2, None] - series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] result = series.null_count() assert result == 1 diff --git a/tests/expr_and_series/operators_test.py b/tests/expr_and_series/operators_test.py index f505c8f972..d7fa63d827 100644 --- a/tests/expr_and_series/operators_test.py +++ b/tests/expr_and_series/operators_test.py @@ -18,10 +18,10 @@ ], ) def test_comparand_operators_scalar_expr( - constructor: Constructor, operator: str, expected: list[bool] + nw_frame_constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a"), operator)(1)) assert_equal_data(result, {"a": expected}) @@ -38,10 +38,10 @@ def test_comparand_operators_scalar_expr( ], ) def test_comparand_operators_expr( - constructor: Constructor, operator: str, expected: list[bool] + nw_frame_constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 1], "b": [0, 0, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a"), operator)(nw.col("b"))) assert_equal_data(result, {"a": expected}) @@ -51,34 +51,34 @@ def test_comparand_operators_expr( [("__and__", [True, False, False, False]), ("__or__", [True, True, True, False])], ) def test_logic_operators_expr( - constructor: Constructor, operator: str, expected: list[bool] + nw_frame_constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [True, True, False, False], "b": [True, False, True, False]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(getattr(nw.col("a"), operator)(nw.col("b"))) assert_equal_data(result, {"a": expected}) def test_logic_operators_expr_kleene( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. request.applymarker(pytest.mark.xfail) data = {"a": [True, True, False, None], "b": [True, None, None, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a") | (nw.col("b"))) - if any(x in str(constructor) for x in ("pandas_constructor",)): + if any(x in str(nw_frame_constructor) for x in ("pandas_constructor",)): expected: list[bool | None] = [True, True, False, False] else: expected = [True, True, None, None] assert_equal_data(result, {"a": expected}) result = df.select(nw.col("a") & (nw.col("b"))) - if any(x in str(constructor) for x in ("pandas_constructor",)): + if any(x in str(nw_frame_constructor) for x in ("pandas_constructor",)): expected = [True, False, False, False] else: expected = [True, None, False, None] @@ -95,19 +95,19 @@ def test_logic_operators_expr_kleene( ], ) def test_logic_operators_expr_scalar( - constructor: Constructor, + nw_frame_constructor: Constructor, operator: str, expected: list[bool], request: pytest.FixtureRequest, ) -> None: if ( - "dask" in str(constructor) + "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10) and operator in {"__rand__", "__ror__"} ): request.applymarker(pytest.mark.xfail) data = {"a": [True, True, False, False]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(a=getattr(nw.col("a"), operator)(False)) assert_equal_data(result, {"a": expected}) @@ -125,10 +125,10 @@ def test_logic_operators_expr_scalar( ], ) def test_comparand_operators_scalar_series( - constructor_eager: ConstructorEager, operator: str, expected: list[bool] + nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 2]} - s = nw.from_native(constructor_eager(data), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = {"a": (getattr(s, operator)(1))} assert_equal_data(result, {"a": expected}) @@ -145,10 +145,10 @@ def test_comparand_operators_scalar_series( ], ) def test_comparand_operators_series( - constructor_eager: ConstructorEager, operator: str, expected: list[bool] + nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 1], "b": [0, 0, 2]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) series, other = df["a"], df["b"] result = {"a": getattr(series, operator)(other)} assert_equal_data(result, {"a": expected}) @@ -164,10 +164,10 @@ def test_comparand_operators_series( ], ) def test_logic_operators_series( - constructor_eager: ConstructorEager, operator: str, expected: list[bool] + nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [True, True, False, False], "b": [True, False, True, False]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) series, other = df["a"], df["b"] result = {"a": getattr(series, operator)(other)} assert_equal_data(result, {"a": expected}) diff --git a/tests/expr_and_series/order_dependent_lazy_test.py b/tests/expr_and_series/order_dependent_lazy_test.py index 70bd234828..532b2ab8a7 100644 --- a/tests/expr_and_series/order_dependent_lazy_test.py +++ b/tests/expr_and_series/order_dependent_lazy_test.py @@ -11,8 +11,8 @@ from tests.utils import Constructor -def test_order_dependent_raises_in_lazy(constructor: Constructor) -> None: - lf = nw.from_native(constructor({"a": [1, 2, 3]})).lazy() +def test_order_dependent_raises_in_lazy(nw_frame_constructor: Constructor) -> None: + lf = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})).lazy() with pytest.raises(InvalidOperationError, match="Order-dependent expressions"): lf.select(nw.col("a").diff()) with pytest.raises(InvalidOperationError, match="Order-dependent expressions"): diff --git a/tests/expr_and_series/over_pushdown_test.py b/tests/expr_and_series/over_pushdown_test.py index 8a8c9795d0..9af8890085 100644 --- a/tests/expr_and_series/over_pushdown_test.py +++ b/tests/expr_and_series/over_pushdown_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_over_pushdown(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_over_pushdown(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, -4, 5, 6, -1], "b": [1, 1, 1, 2, 2, 2], "i": list(range(6))} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( "i", a=nw.col("a").sum().abs().over("b"), diff --git a/tests/expr_and_series/over_test.py b/tests/expr_and_series/over_test.py index 7fbb8f0f9f..8635bd1027 100644 --- a/tests/expr_and_series/over_test.py +++ b/tests/expr_and_series/over_test.py @@ -30,11 +30,11 @@ } -def test_over_single(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_over_single(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -49,14 +49,16 @@ def test_over_single(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_over_std_var(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if "cudf" in str(constructor): +def test_over_std_var( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if "cudf" in str(nw_frame_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -83,10 +85,10 @@ def test_over_std_var(request: pytest.FixtureRequest, constructor: Constructor) assert_equal_data(result, expected) -def test_over_multiple(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_over_multiple(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -100,17 +102,17 @@ def test_over_multiple(constructor: Constructor) -> None: def test_over_cumsum( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_cum)) + df = nw.from_native(nw_eager_constructor(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -128,15 +130,15 @@ def test_over_cumsum( def test_over_cumcount( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_cum)) + df = nw.from_native(nw_eager_constructor(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -154,16 +156,16 @@ def test_over_cumcount( def test_over_cummax( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_cum)) + df = nw.from_native(nw_eager_constructor(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -180,17 +182,17 @@ def test_over_cummax( def test_over_cummin( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_cum)) + df = nw.from_native(nw_eager_constructor(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -208,17 +210,17 @@ def test_over_cummin( def test_over_cumprod( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_cum)) + df = nw.from_native(nw_eager_constructor(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -236,12 +238,12 @@ def test_over_cumprod( def test_over_anonymous_cumulative( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(nw_eager_constructor({"": [1, 1, 2], "b": [4, 5, 6]})) context = ( pytest.raises(NotImplementedError) if df.implementation.is_pyarrow() @@ -266,15 +268,15 @@ def test_over_anonymous_cumulative( def test_over_anonymous_reduction( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # probably bugged request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) context = ( pytest.raises(NotImplementedError) if df.implementation.is_pyarrow() @@ -315,15 +317,15 @@ def test_over_unsupported_dask() -> None: def test_over_shift( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -335,15 +337,15 @@ def test_over_shift( def test_over_diff( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -365,33 +367,33 @@ def test_over_diff( ], ) def test_over_cum_reverse( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, attr: str, expected_b: list[object], ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) if ( - "pandas_nullable" in str(constructor_eager) + "pandas_nullable" in str(nw_eager_constructor) and attr in {"cum_max", "cum_min"} and PANDAS_VERSION < (3, 0) ): # TODO(FBruzzesi): convert to pytest.skip() if the fix does not make it into # `pandas=2.3.4`. Otherwise update version boundary request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = constructor_eager({"a": [1, 1, 2, 2, 2], "b": [4, 5, 7, None, 9]}) + df = nw_eager_constructor({"a": [1, 1, 2, 2, 2], "b": [4, 5, 7, None, 9]}) expr = getattr(nw.col("b"), attr)(reverse=True) result = nw.from_native(df).with_columns(expr.over("a")) expected = {"a": [1, 1, 2, 2, 2], "b": expected_b} assert_equal_data(result, expected) -def test_over_raise_len_change(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_over_raise_len_change(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): nw.from_native(df).select(nw.col("b").drop_nulls().over("a")) @@ -413,15 +415,15 @@ def test_unsupported_over() -> None: def test_over_without_partition_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): # windows not yet supported request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) + df = nw.from_native(nw_frame_constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) result = ( df.with_columns(b=nw.col("a").abs().cum_sum().over(order_by="i")) .sort("i") @@ -432,12 +434,12 @@ def test_over_without_partition_by( def test_aggregation_over_without_partition_by( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw.from_native(constructor_eager({"a": [1, -1, 2], "i": [0, 2, 1]})) + df = nw.from_native(nw_eager_constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) result = ( df.with_columns(b=nw.col("a").diff().sum().over(order_by="i")) .sort("i") @@ -447,34 +449,38 @@ def test_aggregation_over_without_partition_by( assert_equal_data(result, expected) -def test_len_over_2369(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_len_over_2369( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pandas" in str(constructor) and PANDAS_VERSION < (1, 5): + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 5): pytest.skip() - if any(x in str(constructor) for x in ("modin", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("modin", "cudf")): # https://github.com/modin-project/modin/issues/7508 # https://github.com/rapidsai/cudf/issues/18491 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor({"a": [1, 2, 4], "b": ["x", "x", "y"]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 4], "b": ["x", "x", "y"]})) result = df.with_columns(a_len_per_group=nw.len().over("b")).sort("a") expected = {"a": [1, 2, 4], "b": ["x", "x", "y"], "a_len_per_group": [2, 2, 1]} assert_equal_data(result, expected) -def test_over_quantile(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "pyspark", "cudf")): +def test_over_quantile( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "pyspark", "cudf")): # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3, 4, 5, 6], "b": ["x", "x", "x", "y", "y", "y"]} quantile_expr = nw.col("a").quantile(quantile=0.5, interpolation="linear") - native_frame = constructor(data) + native_frame = nw_frame_constructor(data) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): native_frame = native_frame.repartition(npartitions=1) # type: ignore[union-attr] result = ( @@ -494,19 +500,19 @@ def test_over_quantile(constructor: Constructor, request: pytest.FixtureRequest) def test_over_ewm_mean( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin", "cudf")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin", "cudf")): # not implemented request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager) and PANDAS_VERSION < (1, 2): + if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (1, 2): request.applymarker(pytest.mark.xfail(reason="too old, not implemented")) data = {"a": [0.0, 1.0, 3.0, 5.0, 7.0, 7.5], "b": [1, 1, 1, 2, 2, 2]} ewm_expr = nw.col("a").ewm_mean(com=1) result = ( - nw.from_native(constructor_eager(data)) + nw.from_native(nw_eager_constructor(data)) .with_columns(ewm_over_b=ewm_expr.over("b"), ewm_global=ewm_expr) .sort("a") ) @@ -527,13 +533,13 @@ def test_over_ewm_mean( ], ) def test_over_with_nulls_in_partition( - constructor: Constructor, + nw_frame_constructor: Constructor, partition: list[str], expected_min: list[int], expected_max: list[int], ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3300 - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { "a": [1, 1, None, 3, 3], @@ -541,7 +547,7 @@ def test_over_with_nulls_in_partition( "c": [1, 1, None, 3, 4], # second group with nulls "d": [1, 1, 2, 2, 3], # second group without nulls } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) expected = {"b": [1, 3, 4, 5, 6], "bmin": expected_min, "bmax": expected_max} result = df.select( "b", @@ -570,7 +576,7 @@ def test_over_with_nulls_in_partition( ) def test_over_when_then_aggregation_partition_by( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, expr: nw.Expr, expected_c: list[float], ) -> None: @@ -578,13 +584,13 @@ def test_over_when_then_aggregation_partition_by( # tests/imputers/test_ModeImputer.py::TestFit::test_learnt_values_tied_weighted[input_col1-weight_col1-b-False-pandas] # tubular commit: b2ca639aa26e620271b87d43de826006765b1f48 # https://github.com/narwhals-dev/narwhals/issues/3300 - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail(reason="Value mismatch")) data = {"a": [1, 1, None, 3, 3], "b": [1, 3, 4, 5, 6], "g": [1, 1, 2, 3, 3]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select("a", "b", c=expr).sort("b") expected = {"a": [1, 1, None, 3, 3], "b": [1, 3, 4, 5, 6], "c": expected_c} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/pipe_test.py b/tests/expr_and_series/pipe_test.py index d32743e1ea..4d7821faab 100644 --- a/tests/expr_and_series/pipe_test.py +++ b/tests/expr_and_series/pipe_test.py @@ -7,13 +7,13 @@ expected = [4, 16, 36, 64] -def test_pipe_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(input_list)) +def test_pipe_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(input_list)) e = df.select(nw.col("a").pipe(lambda x: x**2)) assert_equal_data(e, {"a": expected}) -def test_pipe_series(constructor_eager: ConstructorEager) -> None: - s = nw.from_native(constructor_eager(input_list), eager_only=True)["a"] +def test_pipe_series(nw_eager_constructor: ConstructorEager) -> None: + s = nw.from_native(nw_eager_constructor(input_list), eager_only=True)["a"] result = s.pipe(lambda x: x**2) assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/quantile_test.py b/tests/expr_and_series/quantile_test.py index 39489db89d..830a65218d 100644 --- a/tests/expr_and_series/quantile_test.py +++ b/tests/expr_and_series/quantile_test.py @@ -22,20 +22,20 @@ ) @pytest.mark.filterwarnings("ignore:the `interpolation=` argument to percentile") def test_quantile_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, interpolation: Literal["nearest", "higher", "lower", "midpoint", "linear"], expected: dict[str, list[float]], request: pytest.FixtureRequest, ) -> None: if ( - any(x in str(constructor) for x in ("dask", "duckdb", "ibis")) + any(x in str(nw_frame_constructor) for x in ("dask", "duckdb", "ibis")) and interpolation != "linear" - ) or "pyspark" in str(constructor): + ) or "pyspark" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) q = 0.3 data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) msg = re.escape( @@ -43,7 +43,7 @@ def test_quantile_expr( ) context = ( pytest.raises(NotImplementedError, match=msg) - if "dask_lazy_p2" in str(constructor) + if "dask_lazy_p2" in str(nw_frame_constructor) else does_not_raise() ) @@ -64,14 +64,14 @@ def test_quantile_expr( ) @pytest.mark.filterwarnings("ignore:the `interpolation=` argument to percentile") def test_quantile_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, interpolation: Literal["nearest", "higher", "lower", "midpoint", "linear"], expected: float, ) -> None: q = 0.3 - series = nw.from_native(constructor_eager({"a": [7.0, 8.0, 9.0]}), eager_only=True)[ - "a" - ].alias("a") + series = nw.from_native( + nw_eager_constructor({"a": [7.0, 8.0, 9.0]}), eager_only=True + )["a"].alias("a") result = series.quantile(quantile=q, interpolation=interpolation) assert_equal_data({"a": [result]}, {"a": [expected]}) diff --git a/tests/expr_and_series/rank_test.py b/tests/expr_and_series/rank_test.py index fb50fdeb59..f726848ccc 100644 --- a/tests/expr_and_series/rank_test.py +++ b/tests/expr_and_series/rank_test.py @@ -61,18 +61,18 @@ @pytest.mark.parametrize("method", rank_methods) @pytest.mark.parametrize("data", [data_int, data_float]) def test_rank_expr( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_eager_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(constructor_eager) + "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): @@ -83,12 +83,12 @@ def test_rank_expr( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(constructor_eager) and method == "average" + if "pyarrow_table" in str(nw_eager_constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").rank(method=method)) expected_data = {"a": expected[method]} @@ -98,18 +98,18 @@ def test_rank_expr( @pytest.mark.parametrize("method", rank_methods) @pytest.mark.parametrize("data", [data_int, data_float]) def test_rank_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_eager_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(constructor_eager) + "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): @@ -120,12 +120,12 @@ def test_rank_series( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(constructor_eager) and method == "average" + if "pyarrow_table" in str(nw_eager_constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"a": df["a"].rank(method=method)} expected_data = {"a": expected[method]} @@ -146,28 +146,28 @@ def test_rank_series_pandas_namesless() -> None: @pytest.mark.parametrize("method", rank_methods) def test_rank_expr_in_over_context( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(constructor) for x in ("pyarrow_table", "dask", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "cudf")): # Pyarrow raises: # > pyarrow.lib.ArrowKeyError: No function registered with name: hash_rank # We can handle that to provide a better error message. # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") - df = nw.from_native(constructor(data_float)) + df = nw.from_native(nw_frame_constructor(data_float)) result = ( df.with_columns(a=nw.col("a").rank(method=method).over("b")).sort("i").select("a") @@ -176,9 +176,9 @@ def test_rank_expr_in_over_context( assert_equal_data(result, expected_data) -def test_invalid_method_raise(constructor_eager: ConstructorEager) -> None: +def test_invalid_method_raise(nw_eager_constructor: ConstructorEager) -> None: method = "invalid_method_name" - df = nw.from_native(constructor_eager(data_float)) + df = nw.from_native(nw_eager_constructor(data_float)) msg = ( "Ranking method must be one of {'average', 'min', 'max', 'dense', 'ordinal'}. " @@ -196,27 +196,27 @@ def test_invalid_method_raise(constructor_eager: ConstructorEager) -> None: @pytest.mark.parametrize("data", [data_int, data_float]) def test_lazy_rank_expr( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(constructor) + "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) @@ -225,12 +225,12 @@ def test_lazy_rank_expr( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(constructor) and method == "average" + if "pyarrow_table" in str(nw_frame_constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(a=nw.col("a").rank(method=method)).sort("i").select("a") expected_data = {"a": expected[method]} @@ -241,27 +241,27 @@ def test_lazy_rank_expr( @pytest.mark.parametrize("data", [data_int, data_float]) def test_lazy_rank_expr_desc( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(constructor) + "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) @@ -270,12 +270,12 @@ def test_lazy_rank_expr_desc( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(constructor) and method == "average" + if "pyarrow_table" in str(nw_frame_constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns(a=nw.col("a").rank(method=method, descending=True)) @@ -289,28 +289,28 @@ def test_lazy_rank_expr_desc( @pytest.mark.parametrize("method", rank_methods) def test_rank_expr_in_over_desc( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(constructor) for x in ("pyarrow_table", "dask", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "cudf")): # Pyarrow raises: # > pyarrow.lib.ArrowKeyError: No function registered with name: hash_rank # We can handle that to provide a better error message. # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") - df = nw.from_native(constructor(data_float)) + df = nw.from_native(nw_frame_constructor(data_float)) result = ( df.with_columns(a=nw.col("a").rank(method=method, descending=True).over("b")) @@ -322,32 +322,32 @@ def test_rank_expr_in_over_desc( def test_rank_with_order_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip(reason="too old") - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") context = ( pytest.raises(NotImplementedError) - if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")) + if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")) else does_not_raise() ) df = nw.from_native( - constructor( + nw_frame_constructor( {"a": [1, 1, 2, 2, 3, 3], "b": [3, None, 4, 3, 5, 6], "i": list(range(6))} ) ) @@ -365,7 +365,7 @@ def test_rank_with_order_by( with context: # gh 3177 - df = nw.from_native(constructor({"i": [0, 1, 2], "j": [1, 2, 1]})) + df = nw.from_native(nw_frame_constructor({"i": [0, 1, 2], "j": [1, 2, 1]})) result = ( df.with_columns(z=nw.col("j").rank("min").over(order_by="i")) .sort("i") @@ -376,28 +376,28 @@ def test_rank_with_order_by( def test_rank_with_order_by_and_partition_by( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): # `rank` is not implemented in Dask # pyarrow only supports aggregations in `over(partition_by=...)` # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip(reason="too old") - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") df = nw.from_native( - constructor( + nw_frame_constructor( { "a": [1, 1, 2, 2, 3, 3], "b": [3, None, 4, 3, 5, 6], @@ -408,7 +408,7 @@ def test_rank_with_order_by_and_partition_by( ) context = ( pytest.raises(NotImplementedError) - if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")) + if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")) else does_not_raise() ) with context: diff --git a/tests/expr_and_series/reduction_test.py b/tests/expr_and_series/reduction_test.py index cba75767ea..4350b253cc 100644 --- a/tests/expr_and_series/reduction_test.py +++ b/tests/expr_and_series/reduction_test.py @@ -26,12 +26,12 @@ ], ) def test_scalar_reduction_select( - constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] + nw_frame_constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(*expr) assert_equal_data(result, expected) @@ -53,17 +53,17 @@ def test_scalar_reduction_select( ], ) def test_scalar_reduction_with_columns( - constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] + nw_frame_constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(*expr).select(*expected.keys()) assert_equal_data(result, expected) -def test_empty_scalar_reduction_select(constructor: Constructor) -> None: +def test_empty_scalar_reduction_select(nw_frame_constructor: Constructor) -> None: data = { "str": [*"abcde"], "int": [0, 1, 2, 3, 4], @@ -78,7 +78,7 @@ def test_empty_scalar_reduction_select(constructor: Constructor) -> None: "sum": nw.col("int").sum(), } - df = nw.from_native(constructor(data)).filter(str="z") + df = nw.from_native(nw_frame_constructor(data)).filter(str="z") result = df.select(**expressions) expected = { @@ -92,8 +92,8 @@ def test_empty_scalar_reduction_select(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_empty_scalar_reduction_with_columns(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_empty_scalar_reduction_with_columns(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { @@ -110,7 +110,7 @@ def test_empty_scalar_reduction_with_columns(constructor: Constructor) -> None: "sum": nw.col("int").sum(), } - df = nw.from_native(constructor(data)).filter(str="z") + df = nw.from_native(nw_frame_constructor(data)).filter(str="z") result = df.with_columns(**expressions) expected: dict[str, list[Any]] = { k: [] for k in chain(df.collect_schema(), expressions) @@ -118,13 +118,13 @@ def test_empty_scalar_reduction_with_columns(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_empty_scalar_reduction_series(constructor_eager: ConstructorEager) -> None: +def test_empty_scalar_reduction_series(nw_eager_constructor: ConstructorEager) -> None: data = { "str": [*"abcde"], "int": [0, 1, 2, 3, 4], "bool": [True, False, False, True, False], } - df = nw.from_native(constructor_eager(data), eager_only=True).filter(str="z") + df = nw.from_native(nw_eager_constructor(data), eager_only=True).filter(str="z") result_s = { "all": [df["bool"].all()], "any": [df["bool"].any()], diff --git a/tests/expr_and_series/replace_strict_test.py b/tests/expr_and_series/replace_strict_test.py index e0fbcecd06..b70bc661d6 100644 --- a/tests/expr_and_series/replace_strict_test.py +++ b/tests/expr_and_series/replace_strict_test.py @@ -25,8 +25,7 @@ def xfail_if_no_default(constructor: Constructor, request: pytest.FixtureRequest) -> None: - lazy_non_polars_constructors = ("dask", "duckdb", "ibis", "pyspark", "sqlframe") - if any(x in str(constructor) for x in lazy_non_polars_constructors): + if constructor.is_lazy and not constructor.is_polars: reason = "non-polars lazy backends require default parameter to be provided" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -40,18 +39,18 @@ def xfail_if_no_default(constructor: Constructor, request: pytest.FixtureRequest ], ) def test_replace_strict_expr_basic( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, old: Sequence[Any] | Mapping[Any, Any], new: Sequence[Any] | None, return_dtype: DType | None, ) -> None: - xfail_if_no_default(constructor, request) + xfail_if_no_default(nw_frame_constructor, request) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor({"a": ["one", "two", "three"]})) + df = nw.from_native(nw_frame_constructor({"a": ["one", "two", "three"]})) result = df.select(nw.col("a").replace_strict(old, new, return_dtype=return_dtype)) assert_equal_data(result, {"a": [1, 2, 3]}) if return_dtype is not None: @@ -67,26 +66,26 @@ def test_replace_strict_expr_basic( ], ) def test_replace_strict_series_basic( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, old: Sequence[Any] | Mapping[Any, Any], new: Sequence[Any] | None, return_dtype: DType | None, ) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) result = df["a"].replace_strict(old, new, return_dtype=return_dtype) assert_equal_data({"a": result}, {"a": ["one", "two", "three"]}) result = df["a"].replace_strict(old, new, return_dtype=return_dtype) assert_equal_data({"a": result}, {"a": ["one", "two", "three"]}) -def test_replace_strict_non_full(constructor: Constructor) -> None: - if "polars" in str(constructor) and polars_lt_v1: +def test_replace_strict_non_full(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor({"a": [1, 2, 3]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) expr = nw.col("a").replace_strict([1, 3], [3, 4], return_dtype=nw.Int64) if isinstance(df, nw.LazyFrame): # NOTE: non-lazy polars backends raise ValueError since `default=no_default` @@ -97,21 +96,21 @@ def test_replace_strict_non_full(constructor: Constructor) -> None: df.select(expr) -def test_replace_strict_invalid_expr(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: +def test_replace_strict_invalid_expr(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) msg = "`new` argument is required if `old` argument is not a Mapping type" with pytest.raises(TypeError, match=msg): df.select(nw.col("a").replace_strict(old=[1, 2, 3])) -def test_replace_strict_invalid_series(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: +def test_replace_strict_invalid_series(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) msg = "`new` argument is required if `old` argument is not a Mapping type" with pytest.raises(TypeError, match=msg): @@ -129,18 +128,20 @@ def test_replace_strict_pandas_unnamed_series() -> None: @pytest.mark.parametrize("return_dtype", [nw.String(), None]) def test_replace_strict_expr_with_default( - constructor: Constructor, request: pytest.FixtureRequest, return_dtype: DType | None + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + return_dtype: DType | None, ) -> None: spark_connect_reason = ( "`mapping_expr[expr]` raises: pyspark.errors.exceptions.base.PySparkTypeError: " "[UNSUPPORTED_DATA_TYPE] Unsupported DataType `Column`." ) - xfail_if_pyspark_connect(constructor, request, reason=spark_connect_reason) + xfail_if_pyspark_connect(nw_frame_constructor, request, reason=spark_connect_reason) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.col("a").replace_strict( [1, 2], ["one", "two"], default="other", return_dtype=return_dtype @@ -151,12 +152,12 @@ def test_replace_strict_expr_with_default( @pytest.mark.parametrize("return_dtype", [nw.String(), None]) def test_replace_strict_series_with_default( - constructor_eager: ConstructorEager, return_dtype: DType | None + nw_eager_constructor: ConstructorEager, return_dtype: DType | None ) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor_eager({"a": [1, 2, 3, 4]})) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, 4]})) result = df.select( df["a"].replace_strict( [1, 2], ["one", "two"], default="other", return_dtype=return_dtype @@ -166,14 +167,14 @@ def test_replace_strict_series_with_default( def test_replace_strict_with_default_and_nulls( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(constructor, request) + xfail_if_pyspark_connect(nw_frame_constructor, request) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor({"a": [1, 2, None, 4]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, None, 4]})) result = df.select( nw.col("a").replace_strict([1, 2], [10, 20], default=99, return_dtype=nw.Int64) ) @@ -181,14 +182,14 @@ def test_replace_strict_with_default_and_nulls( def test_replace_strict_with_default_mapping( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(constructor, request) + xfail_if_pyspark_connect(nw_frame_constructor, request) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.col("a").replace_strict( {1: "one", 2: "two", 3: None}, default="other", return_dtype=nw.String() @@ -198,15 +199,15 @@ def test_replace_strict_with_default_mapping( def test_replace_strict_with_expressified_default( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(constructor, request) + xfail_if_pyspark_connect(nw_frame_constructor, request) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2, 3, 4], "b": ["beluga", "narwhal", "orca", "vaquita"]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").replace_strict( {1: "one", 2: "two"}, default=nw.col("b"), return_dtype=nw.String @@ -216,12 +217,14 @@ def test_replace_strict_with_expressified_default( assert_equal_data(result, {"a": ["one", "two", "orca", "vaquita"]}) -def test_replace_strict_with_series_default(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: +def test_replace_strict_with_series_default( + nw_eager_constructor: ConstructorEager, +) -> None: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2, 3, 4], "b": ["beluga", "narwhal", "orca", "vaquita"]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) series, default = df["a"], df["b"] result = series.replace_strict( {1: "one", 2: "two"}, default=default, return_dtype=nw.String @@ -231,15 +234,15 @@ def test_replace_strict_with_series_default(constructor_eager: ConstructorEager) def test_mapping_key_not_in_expr( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(constructor, request) + xfail_if_pyspark_connect(nw_frame_constructor, request) - if "polars" in str(constructor) and polars_lt_v1: + if "polars" in str(nw_frame_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").replace_strict({1: "one", 2: "two", 3: "three"}, default="hundred") @@ -247,12 +250,12 @@ def test_mapping_key_not_in_expr( assert_equal_data(result, {"a": ["one", "two"]}) -def test_mapping_key_not_in_series(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and polars_lt_v1: +def test_mapping_key_not_in_series(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df["a"].replace_strict({1: "one", 2: "two", 3: "three"}) assert_equal_data({"a": result}, {"a": ["one", "two"]}) diff --git a/tests/expr_and_series/rolling_mean_test.py b/tests/expr_and_series/rolling_mean_test.py index b4c0b9e656..60d61bb4e1 100644 --- a/tests/expr_and_series/rolling_mean_test.py +++ b/tests/expr_and_series/rolling_mean_test.py @@ -39,8 +39,8 @@ } -def test_rolling_mean_expr(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_rolling_mean_expr(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select( **{ name: nw.col("a").rolling_mean(**values["kwargs"]) @@ -55,8 +55,8 @@ def test_rolling_mean_expr(constructor_eager: ConstructorEager) -> None: @pytest.mark.filterwarnings( "ignore:`Series.rolling_mean` is being called from the stable API although considered an unstable feature." ) -def test_rolling_mean_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_rolling_mean_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( **{ @@ -110,7 +110,7 @@ def test_rolling_mean_hypothesis(center: bool, values: list[float]) -> None: # ], ) def test_rolling_mean_expr_lazy_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -118,15 +118,15 @@ def test_rolling_mean_expr_lazy_grouped( *, center: bool, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -135,7 +135,7 @@ def test_rolling_mean_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") @@ -162,18 +162,18 @@ def test_rolling_mean_expr_lazy_grouped( ], ) def test_rolling_mean_expr_lazy_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, *, center: bool, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -181,7 +181,7 @@ def test_rolling_mean_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/rolling_std_test.py b/tests/expr_and_series/rolling_std_test.py index f027b450d9..e8ebb8edc0 100644 --- a/tests/expr_and_series/rolling_std_test.py +++ b/tests/expr_and_series/rolling_std_test.py @@ -70,16 +70,16 @@ @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_std_expr( - constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] + nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): pytest.skip() - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").rolling_std(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -90,16 +90,16 @@ def test_rolling_std_expr( ) @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_std_series( - constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] + nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): pytest.skip() name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].rolling_std(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -188,7 +188,7 @@ def test_rolling_std_series( ], ) def test_rolling_std_expr_lazy_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -196,14 +196,14 @@ def test_rolling_std_expr_lazy_ungrouped( center: bool, ddof: int, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() - if "dask" in str(constructor) and ddof != 1: + if "dask" in str(nw_frame_constructor) and ddof != 1: # Only `ddof=1` is supported pytest.skip() data = { @@ -211,7 +211,7 @@ def test_rolling_std_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") @@ -300,7 +300,7 @@ def test_rolling_std_expr_lazy_ungrouped( ], ) def test_rolling_std_expr_lazy_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -310,14 +310,14 @@ def test_rolling_std_expr_lazy_grouped( ddof: int, ) -> None: if ( - ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) - or ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) - or ("pandas" in str(constructor) and PANDAS_VERSION < (1, 2)) + ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) + or ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) + or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2)) ): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -326,7 +326,7 @@ def test_rolling_std_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/rolling_sum_test.py b/tests/expr_and_series/rolling_sum_test.py index df7b481826..9c920f1dd9 100644 --- a/tests/expr_and_series/rolling_sum_test.py +++ b/tests/expr_and_series/rolling_sum_test.py @@ -41,8 +41,8 @@ } -def test_rolling_sum_expr(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_rolling_sum_expr(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.select( **{ name: nw.col("a").rolling_sum(**values["kwargs"]) @@ -67,18 +67,18 @@ def test_rolling_sum_expr(constructor_eager: ConstructorEager) -> None: ], ) def test_rolling_sum_expr_lazy_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, *, center: bool, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -86,7 +86,7 @@ def test_rolling_sum_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") @@ -113,7 +113,7 @@ def test_rolling_sum_expr_lazy_ungrouped( ], ) def test_rolling_sum_expr_lazy_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -121,15 +121,15 @@ def test_rolling_sum_expr_lazy_grouped( *, center: bool, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "pandas" in str(constructor) and PANDAS_VERSION < (1, 2): + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -138,7 +138,7 @@ def test_rolling_sum_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") @@ -155,8 +155,8 @@ def test_rolling_sum_expr_lazy_grouped( @pytest.mark.filterwarnings( "ignore:`Series.rolling_sum` is being called from the stable API although considered an unstable feature." ) -def test_rolling_sum_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_rolling_sum_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( **{ @@ -206,12 +206,12 @@ def test_rolling_sum_series(constructor_eager: ConstructorEager) -> None: ], ) def test_rolling_sum_expr_invalid_params( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, window_size: int, min_samples: int | None, context: Any, ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) with context: df.select( @@ -260,12 +260,12 @@ def test_rolling_sum_expr_invalid_params( ], ) def test_rolling_sum_series_invalid_params( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, window_size: int, min_samples: int | None, context: Any, ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) with context: df["a"].rolling_sum(window_size=window_size, min_samples=min_samples) diff --git a/tests/expr_and_series/rolling_var_test.py b/tests/expr_and_series/rolling_var_test.py index b38ba5f077..a27e9a23cc 100644 --- a/tests/expr_and_series/rolling_var_test.py +++ b/tests/expr_and_series/rolling_var_test.py @@ -59,20 +59,20 @@ @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_var_expr( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any], ) -> None: name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): # TODO(FBruzzesi): Dask is raising the following error: # NotImplementedError: Partition size is less than overlapping window size. # Try using ``df.repartition`` to increase the partition size. request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.col("a").rolling_var(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -83,16 +83,16 @@ def test_rolling_var_expr( ) @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_var_series( - constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] + nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): pytest.skip() name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].rolling_var(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -191,7 +191,7 @@ def test_rolling_var_hypothesis_polars(center: bool, values: list[float]) -> Non ], ) def test_rolling_var_expr_lazy_ungrouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -199,14 +199,14 @@ def test_rolling_var_expr_lazy_ungrouped( center: bool, ddof: int, ) -> None: - if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() - if "dask" in str(constructor) and ddof != 1: + if "dask" in str(nw_frame_constructor) and ddof != 1: # Only `ddof=1` is supported pytest.skip() data = { @@ -214,7 +214,7 @@ def test_rolling_var_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") @@ -255,7 +255,7 @@ def test_rolling_var_expr_lazy_ungrouped( ], ) def test_rolling_var_expr_lazy_grouped( - constructor: Constructor, + nw_frame_constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -265,14 +265,14 @@ def test_rolling_var_expr_lazy_grouped( ddof: int, ) -> None: if ( - ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) - or ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) - or ("pandas" in str(constructor) and PANDAS_VERSION < (1, 2)) + ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) + or ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) + or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2)) ): pytest.skip() - if any(x in str(constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): # unreliable pytest.skip() data = { @@ -281,7 +281,7 @@ def test_rolling_var_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/round_test.py b/tests/expr_and_series/round_test.py index 0709ad28b7..97cba4ea5c 100644 --- a/tests/expr_and_series/round_test.py +++ b/tests/expr_and_series/round_test.py @@ -7,9 +7,9 @@ @pytest.mark.parametrize("decimals", [0, 1, 2]) -def test_round(constructor: Constructor, decimals: int) -> None: +def test_round(nw_frame_constructor: Constructor, decimals: int) -> None: data = {"a": [2.12345, 2.56789, 3.901234]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) expected_data = {k: [round(e, decimals) for e in v] for k, v in data.items()} @@ -18,9 +18,9 @@ def test_round(constructor: Constructor, decimals: int) -> None: @pytest.mark.parametrize("decimals", [0, 1, 2]) -def test_round_series(constructor_eager: ConstructorEager, decimals: int) -> None: +def test_round_series(nw_eager_constructor: ConstructorEager, decimals: int) -> None: data = {"a": [1.12345, 2.56789, 3.901234]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {k: [round(e, decimals) for e in v] for k, v in data.items()} diff --git a/tests/expr_and_series/sample_test.py b/tests/expr_and_series/sample_test.py index 4ec44a8712..7c8c42fed0 100644 --- a/tests/expr_and_series/sample_test.py +++ b/tests/expr_and_series/sample_test.py @@ -4,9 +4,9 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_sample_fraction(constructor_eager: ConstructorEager) -> None: +def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"a": [1, 2, 3] * 10, "b": [4, 5, 6] * 10}), eager_only=True + nw_eager_constructor({"a": [1, 2, 3] * 10, "b": [4, 5, 6] * 10}), eager_only=True ) result_series = df["a"].sample(fraction=0.1).shape @@ -14,9 +14,9 @@ def test_sample_fraction(constructor_eager: ConstructorEager) -> None: assert result_series == expected_series -def test_sample_with_seed(constructor_eager: ConstructorEager) -> None: +def test_sample_with_seed(nw_eager_constructor: ConstructorEager) -> None: size, n = 100, 10 - df = nw.from_native(constructor_eager({"a": list(range(size))})) + df = nw.from_native(nw_eager_constructor({"a": list(range(size))})) expected = {"res1": [True], "res2": [False]} series = df["a"] seed1 = series.sample(n=n, seed=123) diff --git a/tests/expr_and_series/shift_test.py b/tests/expr_and_series/shift_test.py index a06ff4a872..7c79f7f22f 100644 --- a/tests/expr_and_series/shift_test.py +++ b/tests/expr_and_series/shift_test.py @@ -22,25 +22,25 @@ } -def test_shift(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_shift(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) result = df.with_columns(nw.col("a", "b", "c").shift(2)).filter(nw.col("i") > 1) expected = {"i": [2, 3, 4], "a": [0, 1, 2], "b": [1, 2, 3], "c": [5, 4, 3]} assert_equal_data(result, expected) -def test_shift_lazy(constructor: Constructor) -> None: +def test_shift_lazy(nw_frame_constructor: Constructor) -> None: data = { "i": [None, 1, 2, 3, 4], "a": [0, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1], } - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a", "b", "c").shift(2).over(order_by="i")).filter( nw.col("i") > 1, ~nw.col("i").is_null() ) @@ -49,17 +49,17 @@ def test_shift_lazy(constructor: Constructor) -> None: def test_shift_lazy_grouped( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): # https://github.com/dask/dask/issues/11806 # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a").shift(1).over("b", order_by="i")).sort("i") expected = { "i": [0, 1, 2, 3, 4], @@ -70,8 +70,8 @@ def test_shift_lazy_grouped( assert_equal_data(result, expected) -def test_shift_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_shift_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.with_columns(df["a"].shift(2), df["b"].shift(2), df["c"].shift(2)).filter( nw.col("i") > 1 ) @@ -126,8 +126,8 @@ def test_shift_expr_invalid_params(n: Any, context: Any) -> None: ], ) def test_shift_series_invalid_params( - constructor_eager: ConstructorEager, n: Any, context: Any + nw_eager_constructor: ConstructorEager, n: Any, context: Any ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) with context: df["a"].shift(n) diff --git a/tests/expr_and_series/sin_test.py b/tests/expr_and_series/sin_test.py index b1fed2f501..dd417df474 100644 --- a/tests/expr_and_series/sin_test.py +++ b/tests/expr_and_series/sin_test.py @@ -23,15 +23,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sin_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_sin_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").sin()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sin_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_sin_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.sin() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/skew_test.py b/tests/expr_and_series/skew_test.py index 9be2056dac..8f69d4c8ff 100644 --- a/tests/expr_and_series/skew_test.py +++ b/tests/expr_and_series/skew_test.py @@ -17,9 +17,11 @@ ], ) def test_skew_series( - constructor_eager: ConstructorEager, data: list[float], expected: float | None + nw_eager_constructor: ConstructorEager, data: list[float], expected: float | None ) -> None: - result = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].skew() + result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ + "a" + ].skew() assert_equal_data({"a": [result]}, {"a": [expected]}) @@ -36,22 +38,24 @@ def test_skew_series( ) @pytest.mark.filterwarnings("ignore:.*invalid value:RuntimeWarning:dask") def test_skew_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, data: list[float], expected: float | None, request: pytest.FixtureRequest, ) -> None: - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): # https://github.com/ibis-project/ibis/issues/11176 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pyspark" in str(constructor) and int(request.node.callspec.id[-1]) == 0: + if "pyspark" in str(nw_frame_constructor) and int(request.node.callspec.id[-1]) == 0: # Can not infer schema from empty dataset. pytest.skip() - result = nw.from_native(constructor({"a": data})).select(nw.col("a").skew()) + result = nw.from_native(nw_frame_constructor({"a": data})).select(nw.col("a").skew()) assert_equal_data(result, {"a": [expected]}) - result = nw.from_native(constructor({"a": data})).with_columns(nw.col("a").skew()) + result = nw.from_native(nw_frame_constructor({"a": data})).with_columns( + nw.col("a").skew() + ) assert_equal_data(result, {"a": [expected] * len(data)}) diff --git a/tests/expr_and_series/sqrt_test.py b/tests/expr_and_series/sqrt_test.py index 057401d594..4b93087d40 100644 --- a/tests/expr_and_series/sqrt_test.py +++ b/tests/expr_and_series/sqrt_test.py @@ -22,15 +22,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sqrt_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_sqrt_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").sqrt()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sqrt_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_sqrt_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.sqrt() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/std_test.py b/tests/expr_and_series/std_test.py index d2b3cb14ef..26dec7a39a 100644 --- a/tests/expr_and_series/std_test.py +++ b/tests/expr_and_series/std_test.py @@ -17,8 +17,10 @@ @pytest.mark.parametrize("input_data", [data, data_with_nulls]) -def test_std(constructor: Constructor, input_data: dict[str, list[float | None]]) -> None: - df = nw.from_native(constructor(input_data)) +def test_std( + nw_frame_constructor: Constructor, input_data: dict[str, list[float | None]] +) -> None: + df = nw.from_native(nw_frame_constructor(input_data)) result = df.select( nw.col("a").std(ddof=1).alias("a_ddof_1"), nw.col("a").std(ddof=0).alias("a_ddof_0"), @@ -34,9 +36,9 @@ def test_std(constructor: Constructor, input_data: dict[str, list[float | None]] @pytest.mark.parametrize("input_data", [data, data_with_nulls]) def test_std_series( - constructor_eager: ConstructorEager, input_data: dict[str, list[float | None]] + nw_eager_constructor: ConstructorEager, input_data: dict[str, list[float | None]] ) -> None: - df = nw.from_native(constructor_eager(input_data), eager_only=True) + df = nw.from_native(nw_eager_constructor(input_data), eager_only=True) result = { "a_ddof_1": [df["a"].std(ddof=1)], "a_ddof_0": [df["a"].std(ddof=0)], diff --git a/tests/expr_and_series/str/contains_test.py b/tests/expr_and_series/str/contains_test.py index 7935b6c92f..815e3f2852 100644 --- a/tests/expr_and_series/str/contains_test.py +++ b/tests/expr_and_series/str/contains_test.py @@ -81,7 +81,7 @@ contains_str_pattern_data, ) def test_expr_contains_str_pattern( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, pattern: str, *, @@ -89,15 +89,15 @@ def test_expr_contains_str_pattern( expected_with_null: dict[str, list[Any]], expected_without_null: dict[str, list[Any]], ) -> None: - if "cudf" in str(constructor) and "(?i)" in pattern: + if "cudf" in str(nw_frame_constructor) and "(?i)" in pattern: request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("pets").str.contains(pattern, literal=literal).alias("match") ) - if "pandas_constructor" in str(constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): expected = expected_without_null else: expected = expected_with_null @@ -109,7 +109,7 @@ def test_expr_contains_str_pattern( contains_str_pattern_data, ) def test_series_contains_str_pattern( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, pattern: str, *, @@ -117,13 +117,13 @@ def test_series_contains_str_pattern( expected_with_null: dict[str, list[Any]], expected_without_null: dict[str, list[Any]], ) -> None: - if "cudf" in str(constructor_eager) and "(?i)" in pattern: + if "cudf" in str(nw_eager_constructor) and "(?i)" in pattern: request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(match=df["pets"].str.contains(pattern, literal=literal)) - if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): expected = expected_without_null else: expected = expected_with_null @@ -132,17 +132,17 @@ def test_series_contains_str_pattern( @pytest.mark.parametrize(("expr_data", "literal", "expected"), contains_expr_pattern_data) def test_expr_contains_expr_pattern( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, expr_data: dict[str, list[str]], *, literal: bool, expected: dict[str, list[Any]], ) -> None: - if any(x in str(constructor) for x in EXPR_PATTERN_UNSUPPORTED): + if any(x in str(nw_frame_constructor) for x in EXPR_PATTERN_UNSUPPORTED): request.applymarker(pytest.mark.xfail(reason="Not supported", raises=TypeError)) - df = nw.from_native(constructor(expr_data)) + df = nw.from_native(nw_frame_constructor(expr_data)) result = df.select( nw.col("text").str.contains(nw.col("pattern"), literal=literal).alias("result") ) @@ -151,29 +151,29 @@ def test_expr_contains_expr_pattern( @pytest.mark.parametrize(("expr_data", "literal", "expected"), contains_expr_pattern_data) def test_series_contains_series_pattern( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest, expr_data: dict[str, list[str]], *, literal: bool, expected: dict[str, list[Any]], ) -> None: - if any(x in str(constructor_eager) for x in EXPR_PATTERN_UNSUPPORTED): + if any(x in str(nw_eager_constructor) for x in EXPR_PATTERN_UNSUPPORTED): request.applymarker(pytest.mark.xfail(reason="Not supported", raises=TypeError)) - df = nw.from_native(constructor_eager(expr_data), eager_only=True) + df = nw.from_native(nw_eager_constructor(expr_data), eager_only=True) result = df.select(result=df["text"].str.contains(df["pattern"], literal=literal)) assert_equal_data(result, expected) -def test_expr_contains_literal_vs_regex(constructor: Constructor) -> None: +def test_expr_contains_literal_vs_regex(nw_frame_constructor: Constructor) -> None: """Test that literal=True vs literal=False behaves differently for regex patterns.""" - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("pets").str.contains("Parrot|dove", literal=False).alias("regex_match"), nw.col("pets").str.contains("Parrot|dove", literal=True).alias("literal_match"), ) - if "pandas_constructor" in str(constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): expected: dict[str, Any] = { "regex_match": [False, False, False, True, True, False], "literal_match": [False, False, False, False, True, False], @@ -186,14 +186,14 @@ def test_expr_contains_literal_vs_regex(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_series_contains_literal_vs_regex(constructor_eager: ConstructorEager) -> None: +def test_series_contains_literal_vs_regex(nw_eager_constructor: ConstructorEager) -> None: """Test that literal=True vs literal=False behaves differently for regex patterns.""" - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select( regex_match=df["pets"].str.contains("Parrot|dove", literal=False), literal_match=df["pets"].str.contains("Parrot|dove", literal=True), ) - if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): expected: dict[str, Any] = { "regex_match": [False, False, False, True, True, False], "literal_match": [False, False, False, False, True, False], diff --git a/tests/expr_and_series/str/head_test.py b/tests/expr_and_series/str/head_test.py index d6d09b978e..6ec38da8a9 100644 --- a/tests/expr_and_series/str/head_test.py +++ b/tests/expr_and_series/str/head_test.py @@ -6,15 +6,15 @@ data = {"a": ["foo", "bars"]} -def test_str_head(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_str_head(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").str.head(3)) expected = {"a": ["foo", "bar"]} assert_equal_data(result, expected) -def test_str_head_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_str_head_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = {"a": ["foo", "bar"]} result = df.select(df["a"].str.head(3)) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/len_chars_test.py b/tests/expr_and_series/str/len_chars_test.py index 32a726ab26..0aa7fff982 100644 --- a/tests/expr_and_series/str/len_chars_test.py +++ b/tests/expr_and_series/str/len_chars_test.py @@ -6,15 +6,15 @@ data = {"a": ["foo", "foobar", "Café", "345", "東京"]} -def test_str_len_chars(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_str_len_chars(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").str.len_chars()) expected = {"a": [3, 6, 4, 3, 2]} assert_equal_data(result, expected) -def test_str_len_chars_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_str_len_chars_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = {"a": [3, 6, 4, 3, 2]} result = df.select(df["a"].str.len_chars()) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/pad_test.py b/tests/expr_and_series/str/pad_test.py index 763fd41043..176c82bfdb 100644 --- a/tests/expr_and_series/str/pad_test.py +++ b/tests/expr_and_series/str/pad_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_str_pad_start_series(constructor_eager: ConstructorEager) -> None: +def test_str_pad_start_series(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + nw_eager_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = { @@ -21,9 +21,9 @@ def test_str_pad_start_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_str_pad_start_expr(constructor: Constructor) -> None: +def test_str_pad_start_expr(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + nw_frame_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = df.select( @@ -38,9 +38,9 @@ def test_str_pad_start_expr(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_str_pad_end_series(constructor_eager: ConstructorEager) -> None: +def test_str_pad_end_series(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + nw_eager_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = { @@ -55,9 +55,9 @@ def test_str_pad_end_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_str_pad_end_expr(constructor: Constructor) -> None: +def test_str_pad_end_expr(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + nw_frame_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = df.select( @@ -72,8 +72,8 @@ def test_str_pad_end_expr(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_start_unicode_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_start_unicode_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": ["Café", "345", "東京", None]})) result = df.select(nw.col("a").str.pad_start(6, "日")) expected = {"a": ["日日Café", "日日日345", "日日日日東京", None]} @@ -81,8 +81,8 @@ def test_pad_start_unicode_expr(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_start_unicode_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": ["Café", "345", "東京", None]})) +def test_pad_start_unicode_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": ["Café", "345", "東京", None]})) result = {"a": df["a"].str.pad_start(6, "日")} expected = {"a": ["日日Café", "日日日345", "日日日日東京", None]} @@ -90,8 +90,8 @@ def test_pad_start_unicode_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_pad_end_unicode_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_end_unicode_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": ["Café", "345", "東京", None]})) result = df.select(nw.col("a").str.pad_end(6, "日")) expected = {"a": ["Café日日", "345日日日", "東京日日日日", None]} @@ -99,8 +99,8 @@ def test_pad_end_unicode_expr(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_end_unicode_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": ["Café", "345", "東京", None]})) +def test_pad_end_unicode_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": ["Café", "345", "東京", None]})) result = {"a": df["a"].str.pad_end(6, "日")} expected = {"a": ["Café日日", "345日日日", "東京日日日日", None]} diff --git a/tests/expr_and_series/str/replace_test.py b/tests/expr_and_series/str/replace_test.py index e6f49f409b..c5c9968d0e 100644 --- a/tests/expr_and_series/str/replace_test.py +++ b/tests/expr_and_series/str/replace_test.py @@ -99,7 +99,7 @@ ("data", "pattern", "value", "n", "literal", "expected"), replace_data ) def test_str_replace_series_scalar( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -107,7 +107,7 @@ def test_str_replace_series_scalar( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.replace( pattern=pattern, value=value, n=n, literal=literal @@ -119,14 +119,14 @@ def test_str_replace_series_scalar( ("data", "pattern", "value", "literal", "expected"), replace_all_data ) def test_str_replace_all_series_scalar( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.replace_all(pattern=pattern, value=value, literal=literal) assert_equal_data({"a": result_series}, expected) @@ -136,7 +136,7 @@ def test_str_replace_all_series_scalar( ("data", "pattern", "value", "n", "literal", "expected"), replace_data ) def test_str_replace_expr_scalar( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, data: dict[str, list[str]], pattern: str, @@ -145,14 +145,14 @@ def test_str_replace_expr_scalar( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): request.applymarker( pytest.mark.xfail( - reason=f"{constructor} only supports `replace_all`.", + reason=f"{nw_frame_constructor} only supports `replace_all`.", raises=NotImplementedError, ) ) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_df = df.select( nw.col("a").str.replace(pattern=pattern, value=value, n=n, literal=literal) ) @@ -163,14 +163,14 @@ def test_str_replace_expr_scalar( ("data", "pattern", "value", "literal", "expected"), replace_all_data ) def test_str_replace_all_expr_scalar( - constructor: Constructor, + nw_frame_constructor: Constructor, data: dict[str, list[str]], pattern: str, value: str, literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").str.replace_all(pattern=pattern, value=value, literal=literal) ) @@ -181,7 +181,7 @@ def test_str_replace_all_expr_scalar( ("data", "pattern", "value", "n", "literal", "expected"), replace_data_multivalue ) def test_str_replace_series_multivalue( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -190,11 +190,13 @@ def test_str_replace_series_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) - if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): + df = nw.from_native(nw_eager_constructor(data), eager_only=True) + if any( + x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") + ): request.applymarker( pytest.mark.xfail( - reason=f"{constructor_eager} does not support multivalue replacement", + reason=f"{nw_eager_constructor} does not support multivalue replacement", raises=TypeError, ) ) @@ -209,7 +211,7 @@ def test_str_replace_series_multivalue( ("data", "pattern", "value", "literal", "expected"), replace_all_data_multivalue ) def test_str_replace_all_series_multivalue( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -217,15 +219,17 @@ def test_str_replace_all_series_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): + if any( + x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") + ): request.applymarker( pytest.mark.xfail( - reason=f"{constructor_eager} only supports `replace_all`.", + reason=f"{nw_eager_constructor} only supports `replace_all`.", raises=TypeError, ) ) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.replace_all( pattern=pattern, value=df[value], literal=literal ) @@ -236,7 +240,7 @@ def test_str_replace_all_series_multivalue( ("data", "pattern", "value", "n", "literal", "expected"), replace_data_multivalue ) def test_str_replace_expr_multivalue( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, data: dict[str, list[str]], pattern: str, @@ -245,24 +249,25 @@ def test_str_replace_expr_multivalue( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): request.applymarker( pytest.mark.xfail( - reason=f"{constructor} only supports `replace_all`.", + reason=f"{nw_frame_constructor} only supports `replace_all`.", raises=NotImplementedError, ) ) elif any( - x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(nw_frame_constructor) + for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ): request.applymarker( pytest.mark.xfail( - reason=f"{constructor} does not support multivalue replacement", + reason=f"{nw_frame_constructor} does not support multivalue replacement", raises=TypeError, ) ) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_df = df.select( nw.col("a").str.replace( pattern=pattern, value=nw.col(value), n=n, literal=literal @@ -275,7 +280,7 @@ def test_str_replace_expr_multivalue( ("data", "pattern", "value", "literal", "expected"), replace_all_data_multivalue ) def test_str_replace_all_expr_multivalue( - constructor: Constructor, + nw_frame_constructor: Constructor, data: dict[str, list[str]], pattern: str, value: str, @@ -283,29 +288,32 @@ def test_str_replace_all_expr_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - if any(x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf")): + if any( + x in str(nw_frame_constructor) + for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + ): request.applymarker( pytest.mark.xfail( - reason=f"{constructor} does not support multivalue replacement", + reason=f"{nw_frame_constructor} does not support multivalue replacement", raises=TypeError, ) ) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.col("a").str.replace_all(pattern=pattern, value=nw.col(value), literal=literal) ) assert_equal_data(result, expected) -def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: +def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> None: context: Any only_str_supported = pytest.raises( TypeError, match=r"only supports str replacement values" ) multivalue_binary_n = pytest.raises(Exception, match=r"'n > 1' not yet supported") - df = nw.from_native(constructor_eager({"a": ["abc", "def", "ab"]})) + df = nw.from_native(nw_eager_constructor({"a": ["abc", "def", "ab"]})) ## .str.replace # all eager backends support scalar replacement @@ -314,7 +322,9 @@ def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: # pyarrow, pandas, modin and cudf do not support multivalue replacement context = nullcontext() - if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): + if any( + x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") + ): context = only_str_supported with context: @@ -322,7 +332,9 @@ def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: # no backends support multivalue AND n > 1; others error out on multivalue context = ( - multivalue_binary_n if "polars" in str(constructor_eager) else only_str_supported + multivalue_binary_n + if "polars" in str(nw_eager_constructor) + else only_str_supported ) with context: df["a"].str.replace("ab", df["a"], n=2) @@ -334,7 +346,7 @@ def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: context = ( only_str_supported if any( - x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf") + x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") ) else nullcontext() ) @@ -342,19 +354,19 @@ def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: df["a"].str.replace_all("ab", df["a"]) -def test_str_replace_errors_expr(constructor: Constructor) -> None: +def test_str_replace_errors_expr(nw_frame_constructor: Constructor) -> None: context: Any not_implemented = pytest.raises(NotImplementedError) only_str_supported = pytest.raises( TypeError, match=r"only supports str replacement values" ) - df = nw.from_native(constructor({"a": ["abc", "def", "ab"]})) + df = nw.from_native(nw_frame_constructor({"a": ["abc", "def", "ab"]})) ## .str.replace context = ( not_implemented - if any(x in str(constructor) for x in ("duckdb", "ibis", "pyspark")) + if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis", "pyspark")) else nullcontext() ) with context: @@ -362,10 +374,11 @@ def test_str_replace_errors_expr(constructor: Constructor) -> None: ## .str.replace multivalue; some dont implement replace, others dont support multivalue context = nullcontext() - if any(x in str(constructor) for x in ("duckdb", "ibis", "pyspark")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis", "pyspark")): context = not_implemented elif any( - x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(nw_frame_constructor) + for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ): context = only_str_supported @@ -379,7 +392,8 @@ def test_str_replace_errors_expr(constructor: Constructor) -> None: context = ( only_str_supported if any( - x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(nw_frame_constructor) + for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ) else nullcontext() ) diff --git a/tests/expr_and_series/str/slice_test.py b/tests/expr_and_series/str/slice_test.py index 87486e6927..7f0ea0719f 100644 --- a/tests/expr_and_series/str/slice_test.py +++ b/tests/expr_and_series/str/slice_test.py @@ -15,9 +15,9 @@ [(1, 2, {"a": ["da", "df"]}), (-2, None, {"a": ["as", "as"]})], ) def test_str_slice( - constructor: Constructor, offset: int, length: int | None, expected: Any + nw_frame_constructor: Constructor, offset: int, length: int | None, expected: Any ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("a").str.slice(offset, length)) assert_equal_data(result_frame, expected) @@ -27,9 +27,9 @@ def test_str_slice( [(1, 2, {"a": ["da", "df"]}), (-2, None, {"a": ["as", "as"]})], ) def test_str_slice_series( - constructor_eager: ConstructorEager, offset: int, length: int | None, expected: Any + nw_eager_constructor: ConstructorEager, offset: int, length: int | None, expected: Any ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.slice(offset, length) assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/split_test.py b/tests/expr_and_series/str/split_test.py index f206b84e35..15c3f21157 100644 --- a/tests/expr_and_series/str/split_test.py +++ b/tests/expr_and_series/str/split_test.py @@ -18,16 +18,17 @@ (",", {"s": [["foo bar"], ["foo_bar"], ["foo_bar_baz"], ["foo", "bar"]]}), ], ) -def test_str_split(constructor: Constructor, by: str, expected: Any) -> None: - if "cudf" not in str(constructor) and ( - str(constructor).startswith("pandas") and "pyarrow" not in str(constructor) +def test_str_split(nw_frame_constructor: Constructor, by: str, expected: Any) -> None: + if "cudf" not in str(nw_frame_constructor) and ( + str(nw_frame_constructor).startswith("pandas") + and "pyarrow" not in str(nw_frame_constructor) ): - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df.select(nw.col("s").str.split(by=by)) return - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("s").str.split(by=by)) assert_equal_data(result_frame, expected) @@ -40,17 +41,17 @@ def test_str_split(constructor: Constructor, by: str, expected: Any) -> None: ], ) def test_str_split_series( - constructor_eager: ConstructorEager, by: str, expected: Any + nw_eager_constructor: ConstructorEager, by: str, expected: Any ) -> None: - if "cudf" not in str(constructor_eager) and ( - str(constructor_eager).startswith("pandas") - and "pyarrow" not in str(constructor_eager) + if "cudf" not in str(nw_eager_constructor) and ( + str(nw_eager_constructor).startswith("pandas") + and "pyarrow" not in str(nw_eager_constructor) ): - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df["s"].str.split(by=by) return - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["s"].str.split(by=by) assert_equal_data({"s": result_series}, expected) diff --git a/tests/expr_and_series/str/starts_with_ends_with_test.py b/tests/expr_and_series/str/starts_with_ends_with_test.py index 73f60a355d..31beae998a 100644 --- a/tests/expr_and_series/str/starts_with_ends_with_test.py +++ b/tests/expr_and_series/str/starts_with_ends_with_test.py @@ -9,29 +9,29 @@ data = {"a": ["fdas", "edfas"]} -def test_ends_with(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_ends_with(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").str.ends_with("das")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_ends_with_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_ends_with_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].str.ends_with("das")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_starts_with(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)).lazy() +def test_starts_with(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)).lazy() result = df.select(nw.col("a").str.starts_with("fda")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_starts_with_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_starts_with_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.select(df["a"].str.starts_with("fda")) expected = {"a": [True, False]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/strip_chars_test.py b/tests/expr_and_series/str/strip_chars_test.py index 8944bce4de..6546f2576f 100644 --- a/tests/expr_and_series/str/strip_chars_test.py +++ b/tests/expr_and_series/str/strip_chars_test.py @@ -15,15 +15,15 @@ [(None, {"a": ["foobar", "bar", "baz"]}), ("foo", {"a": ["bar", "bar\n", " baz"]})], ) def test_str_strip_chars( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, characters: str | None, expected: Any, ) -> None: - if "ibis" in str(constructor) and characters is not None: + if "ibis" in str(nw_frame_constructor) and characters is not None: request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("a").str.strip_chars(characters)) assert_equal_data(result_frame, expected) @@ -33,9 +33,9 @@ def test_str_strip_chars( [(None, {"a": ["foobar", "bar", "baz"]}), ("foo", {"a": ["bar", "bar\n", " baz"]})], ) def test_str_strip_chars_series( - constructor_eager: ConstructorEager, characters: str | None, expected: Any + nw_eager_constructor: ConstructorEager, characters: str | None, expected: Any ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.strip_chars(characters) assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/tail_test.py b/tests/expr_and_series/str/tail_test.py index 8aa9d66c02..5e0e41e3af 100644 --- a/tests/expr_and_series/str/tail_test.py +++ b/tests/expr_and_series/str/tail_test.py @@ -6,16 +6,16 @@ data = {"a": ["foo", "bars"]} -def test_str_tail(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_str_tail(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) expected = {"a": ["foo", "ars"]} result_frame = df.select(nw.col("a").str.tail(3)) assert_equal_data(result_frame, expected) -def test_str_tail_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_str_tail_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = {"a": ["foo", "ars"]} result_series = df["a"].str.tail(3) diff --git a/tests/expr_and_series/str/to_date_test.py b/tests/expr_and_series/str/to_date_test.py index d1f7558c9f..12ef33824c 100644 --- a/tests/expr_and_series/str/to_date_test.py +++ b/tests/expr_and_series/str/to_date_test.py @@ -16,16 +16,16 @@ def test_to_date_with_fmt_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "cudf" in str(constructor_eager) or ( - "pandas" in str(constructor_eager) - and not uses_pyarrow_backend(constructor=constructor_eager) + if "cudf" in str(nw_eager_constructor) or ( + "pandas" in str(nw_eager_constructor) + and not uses_pyarrow_backend(constructor=nw_eager_constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_date( + result = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_date( format="%Y-%m-%d" ) assert isinstance(result.dtype, nw.Date) @@ -33,34 +33,37 @@ def test_to_date_with_fmt_series( def test_to_date_infer_fmt_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "cudf" in str(constructor_eager) or ( - "pandas" in str(constructor_eager) - and not uses_pyarrow_backend(constructor=constructor_eager) + if "cudf" in str(nw_eager_constructor) or ( + "pandas" in str(nw_eager_constructor) + and not uses_pyarrow_backend(constructor=nw_eager_constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_date() + result = nw.from_native(nw_eager_constructor(data), eager_only=True)[ + "a" + ].str.to_date() assert isinstance(result.dtype, nw.Date) assert_equal_data({"a": result}, expected) def test_to_date_with_fmt_expr( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if "cudf" in str(constructor) or ( - "pandas" in str(constructor) and not uses_pyarrow_backend(constructor=constructor) + if "cudf" in str(nw_frame_constructor) or ( + "pandas" in str(nw_frame_constructor) + and not uses_pyarrow_backend(constructor=nw_frame_constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "not implemented" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( a=nw.col("a").str.to_date(format="%Y-%m-%d") ) result_schema = result.collect_schema() @@ -70,22 +73,25 @@ def test_to_date_with_fmt_expr( def test_to_date_infer_fmt_expr( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if "cudf" in str(constructor) or ( - "pandas" in str(constructor) and not uses_pyarrow_backend(constructor=constructor) + if "cudf" in str(nw_frame_constructor) or ( + "pandas" in str(nw_frame_constructor) + and not uses_pyarrow_backend(constructor=nw_frame_constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): reason = "Cannot infer format" request.applymarker(pytest.mark.xfail(reason=reason)) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "not implemented" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(constructor(data)).select(a=nw.col("a").str.to_date()) + result = nw.from_native(nw_frame_constructor(data)).select( + a=nw.col("a").str.to_date() + ) result_schema = result.collect_schema() assert isinstance(result_schema["a"], nw.Date) diff --git a/tests/expr_and_series/str/to_datetime_test.py b/tests/expr_and_series/str/to_datetime_test.py index b98755a0cc..8b16a2919a 100644 --- a/tests/expr_and_series/str/to_datetime_test.py +++ b/tests/expr_and_series/str/to_datetime_test.py @@ -23,14 +23,14 @@ data = {"a": ["2020-01-01T12:34:56"]} -def test_to_datetime(constructor: Constructor) -> None: - if "cudf" in str(constructor): +def test_to_datetime(nw_frame_constructor: Constructor) -> None: + if "cudf" in str(nw_frame_constructor): expected = "2020-01-01T12:34:56.000000000" else: expected = "2020-01-01 12:34:56" result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .lazy() .select(b=nw.col("a").str.to_datetime(format="%Y-%m-%dT%H:%M:%S")) ) @@ -41,14 +41,14 @@ def test_to_datetime(constructor: Constructor) -> None: assert str(result_item) == expected -def test_to_datetime_series(constructor_eager: ConstructorEager) -> None: - if "cudf" in str(constructor_eager): +def test_to_datetime_series(nw_eager_constructor: ConstructorEager) -> None: + if "cudf" in str(nw_eager_constructor): expected = "2020-01-01T12:34:56.000000000" else: expected = "2020-01-01 12:34:56" result = ( - nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_datetime( + nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_datetime( format="%Y-%m-%dT%H:%M:%S" ) ).item(0) @@ -80,27 +80,27 @@ def test_to_datetime_series(constructor_eager: ConstructorEager) -> None: ) def test_to_datetime_infer_fmt( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, data: dict[str, list[str]], expected: str, expected_cudf: str, expected_pyspark: str, ) -> None: if ( - ("polars" in str(constructor) and str(data["a"][0]).isdigit()) - or "duckdb" in str(constructor) - or ("pyspark" in str(constructor) and data["a"][0] == "20240101123456") - or "ibis" in str(constructor) + ("polars" in str(nw_frame_constructor) and str(data["a"][0]).isdigit()) + or "duckdb" in str(nw_frame_constructor) + or ("pyspark" in str(nw_frame_constructor) and data["a"][0] == "20240101123456") + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): expected = expected_cudf - elif "pyspark" in str(constructor): + elif "pyspark" in str(nw_frame_constructor): expected = expected_pyspark result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .lazy() .select(b=nw.col("a").str.to_datetime()) .collect() @@ -131,29 +131,29 @@ def test_to_datetime_infer_fmt( ) def test_to_datetime_series_infer_fmt( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], expected: str, expected_cudf: str, ) -> None: - if "polars" in str(constructor_eager) and str(data["a"][0]).isdigit(): + if "polars" in str(nw_eager_constructor) and str(data["a"][0]).isdigit(): request.applymarker(pytest.mark.xfail) - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): expected = expected_cudf result = ( - nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_datetime() + nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_datetime() ).item(0) assert str(result) == expected def test_to_datetime_infer_fmt_from_date( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("duckdb", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis")): request.applymarker(pytest.mark.xfail) data = {"z": ["2020-01-01", "2020-01-02", None]} - if "pyspark" in str(constructor): + if "pyspark" in str(nw_frame_constructor): expected = [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), @@ -162,7 +162,9 @@ def test_to_datetime_infer_fmt_from_date( else: expected = [datetime(2020, 1, 1), datetime(2020, 1, 2), None] result = ( - nw.from_native(constructor(data)).lazy().select(nw.col("z").str.to_datetime()) + nw.from_native(nw_frame_constructor(data)) + .lazy() + .select(nw.col("z").str.to_datetime()) ) assert_equal_data(result, {"z": expected}) @@ -215,25 +217,30 @@ def test_pyarrow_infer_datetime_raise_inconsistent_date_fmt( @pytest.mark.parametrize("format", [None, "%Y-%m-%dT%H:%M:%S%z"]) def test_to_datetime_tz_aware( - constructor: Constructor, request: pytest.FixtureRequest, format: str | None + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, format: str | None ) -> None: - if is_pyarrow_windows_no_tzdata(constructor) or ( - "sqlframe" in str(constructor) and format is not None and is_windows() + if is_pyarrow_windows_no_tzdata(nw_frame_constructor) or ( + "sqlframe" in str(nw_frame_constructor) and format is not None and is_windows() ): # NOTE: For `sqlframe` see https://github.com/narwhals-dev/narwhals/pull/2263#discussion_r2009101659 pytest.skip() - if "cudf" in str(constructor): + if "cudf" in str(nw_frame_constructor): # cuDF does not yet support timezone-aware datetimes request.applymarker(pytest.mark.xfail) context: AbstractContextManager[Any] = ( pytest.raises(NotImplementedError) - if any(x in str(constructor) for x in ("duckdb", "ibis")) and format is None + if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis")) + and format is None else does_not_raise() ) - if "polars" in str(constructor) and POLARS_VERSION >= (1, 33, 0) and format is None: + if ( + "polars" in str(nw_frame_constructor) + and POLARS_VERSION >= (1, 33, 0) + and format is None + ): # Polars 1.33.0+ raises an error when parsing timezone-aware datetimes without specifying the timezone context = pytest.raises(ComputeError) - df = nw.from_native(constructor({"a": ["2020-01-01T01:02:03+0100"]})) + df = nw.from_native(nw_frame_constructor({"a": ["2020-01-01T01:02:03+0100"]})) with context: result = df.with_columns(b=nw.col("a").str.to_datetime(format)) assert isinstance(result.collect_schema()["b"], nw.Datetime) diff --git a/tests/expr_and_series/str/to_titlecase_test.py b/tests/expr_and_series/str/to_titlecase_test.py index ae61c3ecd2..472cfb43ad 100644 --- a/tests/expr_and_series/str/to_titlecase_test.py +++ b/tests/expr_and_series/str/to_titlecase_test.py @@ -19,23 +19,23 @@ def test_str_to_titlecase_expr( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 2): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 2): reason = "version too old, duckdb 1.2 required for LambdaExpression." pytest.skip(reason=reason) - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("a").str.to_titlecase()) assert_equal_data(result_frame, expected) -def test_str_to_titlecase_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_str_to_titlecase_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.to_titlecase() assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py b/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py index 7c5c39a481..7f29c8f47e 100644 --- a/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py +++ b/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py @@ -10,9 +10,11 @@ ("data", "expected"), [({"a": ["foo", "bar"]}, {"a": ["FOO", "BAR"]})] ) def test_str_to_uppercase( - constructor: Constructor, data: dict[str, list[str]], expected: dict[str, list[str]] + nw_frame_constructor: Constructor, + data: dict[str, list[str]], + expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("a").str.to_uppercase()) assert_equal_data(result_frame, expected) @@ -22,11 +24,11 @@ def test_str_to_uppercase( ("data", "expected"), [({"a": ["foo", "bar"]}, {"a": ["FOO", "BAR"]})] ) def test_str_to_uppercase_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.to_uppercase() assert_equal_data({"a": result_series}, expected) @@ -47,9 +49,11 @@ def test_str_to_uppercase_series( ], ) def test_str_to_lowercase( - constructor: Constructor, data: dict[str, list[str]], expected: dict[str, list[str]] + nw_frame_constructor: Constructor, + data: dict[str, list[str]], + expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result_frame = df.select(nw.col("a").str.to_lowercase()) assert_equal_data(result_frame, expected) @@ -70,11 +74,11 @@ def test_str_to_lowercase( ], ) def test_str_to_lowercase_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, data: dict[str, list[str]], expected: dict[str, list[str]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result_series = df["a"].str.to_lowercase() assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/zfill_test.py b/tests/expr_and_series/str/zfill_test.py index 78f59cecb1..70b2f9d8af 100644 --- a/tests/expr_and_series/str/zfill_test.py +++ b/tests/expr_and_series/str/zfill_test.py @@ -16,51 +16,53 @@ expected = {"a": ["-01", "+01", "001", "012", "123", "99999", "+9999", None]} -def test_str_zfill(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if uses_pyarrow_backend(constructor) and PANDAS_VERSION < (3,): +def test_str_zfill( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if uses_pyarrow_backend(nw_frame_constructor) and PANDAS_VERSION < (3,): reason = ( "pandas with pyarrow backend doesn't support str.zfill, see " "https://github.com/pandas-dev/pandas/issues/61485" ) request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(constructor) and PANDAS_VERSION < (1, 5): + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 5): reason = "different zfill behavior" pytest.skip(reason=reason) - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 5): reason = ( "`TypeError: argument 'length': 'Expr' object cannot be interpreted as an integer`" "in `expr.str.slice(1, length)`" ) pytest.skip(reason=reason) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").str.zfill(3)) assert_equal_data(result, expected) def test_str_zfill_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if uses_pyarrow_backend(constructor_eager) and PANDAS_VERSION < (3,): + if uses_pyarrow_backend(nw_eager_constructor) and PANDAS_VERSION < (3,): reason = ( "pandas with pyarrow backend doesn't support str.zfill, see " "https://github.com/pandas-dev/pandas/issues/61485" ) request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(constructor_eager) and PANDAS_VERSION < (1, 5): + if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (1, 5): reason = "different zfill behavior" pytest.skip(reason=reason) - if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 5): reason = ( "`TypeError: argument 'length': 'Expr' object cannot be interpreted as an integer`" "in `expr.str.slice(1, length)`" ) pytest.skip(reason=reason) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df["a"].str.zfill(3) assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/struct_/field_test.py b/tests/expr_and_series/struct_/field_test.py index a351c31500..2e396f3a48 100644 --- a/tests/expr_and_series/struct_/field_test.py +++ b/tests/expr_and_series/struct_/field_test.py @@ -8,19 +8,21 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_get_field_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: +def test_get_field_expr( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - if any(backend in str(constructor) for backend in ("dask", "modin")): + if any(backend in str(nw_frame_constructor) for backend in ("dask", "modin")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor) and PANDAS_VERSION < (2, 2, 0): + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 2, 0): pytest.skip() data = {"user": [{"id": "0", "name": "john"}, {"id": "1", "name": "jane"}]} - df_native = constructor(data) + df_native = nw_frame_constructor(data) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): import pandas as pd df_native = cast("pd.DataFrame", df_native).assign( @@ -45,22 +47,22 @@ def test_get_field_expr(request: pytest.FixtureRequest, constructor: Constructor def test_get_field_series( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - if any(backend in str(constructor_eager) for backend in ("modin",)): + if any(backend in str(nw_eager_constructor) for backend in ("modin",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager) and PANDAS_VERSION < (2, 2, 0): + if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2, 0): pytest.skip() data = {"user": [{"id": "0", "name": "john"}, {"id": "1", "name": "jane"}]} expected = {"id": ["0", "1"], "name": ["john", "jane"]} _expected = expected.copy() - df_native = constructor_eager(data) + df_native = nw_eager_constructor(data) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): import pandas as pd df_native = cast("pd.DataFrame", df_native).assign( diff --git a/tests/expr_and_series/struct_test.py b/tests/expr_and_series/struct_test.py index b7f1eae1ca..e8b3c3afc1 100644 --- a/tests/expr_and_series/struct_test.py +++ b/tests/expr_and_series/struct_test.py @@ -40,15 +40,15 @@ def maybe_skip(constructor: Constructor | ConstructorEager) -> None: ) def test_struct_positional_exprs( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, exprs: tuple[nw.Expr | list[nw.Expr], ...], ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.struct(*exprs)) expected = { @@ -63,14 +63,14 @@ def test_struct_positional_exprs( def test_struct_named_exprs( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.struct(x="a", y="b").alias("struct")) expected = { @@ -81,14 +81,14 @@ def test_struct_named_exprs( def test_struct_positional_and_named( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.struct("a", z="c").alias("struct")) expected = { @@ -99,14 +99,14 @@ def test_struct_positional_and_named( def test_struct_with_expressions( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.struct(nw.col("a") * 2, nw.col("c").str.len_chars()).alias("struct") ) @@ -117,14 +117,14 @@ def test_struct_with_expressions( def test_struct_with_literals( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.struct("a", x="c", y=nw.lit(False)).alias("struct")) expected = { @@ -138,8 +138,8 @@ def test_struct_with_literals( assert_equal_data(result, expected) -def test_struct_raise_no_exprs(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_struct_raise_no_exprs(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(ValueError, match="expected at least 1 expression in 'struct'"): df.select(nw.struct().alias("struct")) @@ -148,16 +148,16 @@ def test_struct_raise_no_exprs(constructor: Constructor) -> None: def test_struct_with_schema( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=constructor) + maybe_skip(constructor=nw_frame_constructor) data_numeric = {"a": [1, 2, 3], "b": [4.0, 5.0, 6.0]} schema = {"a": nw.Float64(), "b": nw.Float32()} - df = nw.from_native(constructor(data_numeric)) + df = nw.from_native(nw_frame_constructor(data_numeric)) result = df.select(nw.struct("a", "b").cast(nw.Struct(schema)).alias("struct")) assert result.collect_schema()["struct"] == nw.Struct(schema) @@ -167,10 +167,10 @@ def test_struct_with_schema( assert_equal_data(result, expected) -def test_struct_with_series(constructor_eager: ConstructorEager) -> None: - maybe_skip(constructor=constructor_eager) +def test_struct_with_series(nw_eager_constructor: ConstructorEager) -> None: + maybe_skip(constructor=nw_eager_constructor) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) s_a, s_b = df.get_column("a"), df.get_column("b") result = df.select(nw.struct(s_a, s_b).alias("struct")) @@ -181,10 +181,10 @@ def test_struct_with_series(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_struct_mixed_series_and_exprs(constructor_eager: ConstructorEager) -> None: - maybe_skip(constructor=constructor_eager) +def test_struct_mixed_series_and_exprs(nw_eager_constructor: ConstructorEager) -> None: + maybe_skip(constructor=nw_eager_constructor) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) s_a = df.get_column("a") result = df.select(nw.struct(s_a, nw.col("c")).alias("struct")) @@ -195,10 +195,10 @@ def test_struct_mixed_series_and_exprs(constructor_eager: ConstructorEager) -> N assert_equal_data(result, expected) -def test_struct_named_with_series(constructor_eager: ConstructorEager) -> None: - maybe_skip(constructor=constructor_eager) +def test_struct_named_with_series(nw_eager_constructor: ConstructorEager) -> None: + maybe_skip(constructor=nw_eager_constructor) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) s_a = df.get_column("a") result = df.select(nw.struct(x=s_a, y="b").alias("struct")) diff --git a/tests/expr_and_series/sum_horizontal_test.py b/tests/expr_and_series/sum_horizontal_test.py index 94cc32d4b0..dcd0e1e16f 100644 --- a/tests/expr_and_series/sum_horizontal_test.py +++ b/tests/expr_and_series/sum_horizontal_test.py @@ -8,9 +8,9 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_sumh(constructor: Constructor) -> None: +def test_sumh(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(horizontal_sum=nw.sum_horizontal("a", nw.col("b"))) expected = { "a": [1, 3, 2], @@ -21,18 +21,18 @@ def test_sumh(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_sumh_nullable(constructor: Constructor) -> None: +def test_sumh_nullable(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 8, 3], "b": [4, 5, None], "i": [0, 1, 2]} expected = {"hsum": [5, 13, 3], "i": [0, 1, 2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(hsum=nw.sum_horizontal("a", "b"), i="i").sort("i") assert_equal_data(result, expected) -def test_sumh_all(constructor: Constructor) -> None: +def test_sumh_all(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [10, 20, 30]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.sum_horizontal(nw.all().name.suffix("_foo"))) expected = {"a_foo": [11, 22, 33]} assert_equal_data(result, expected) @@ -41,19 +41,19 @@ def test_sumh_all(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_sumh_aggregations(constructor: Constructor) -> None: +def test_sumh_aggregations(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [10, 20, 30]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.sum_horizontal(nw.all().mean().name.suffix("_foo"))) expected = {"a_foo": [22]} assert_equal_data(result, expected) -def test_sumh_transformations(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_sumh_transformations(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(d=nw.sum_horizontal("a", nw.col("b").sum(), "c")) expected: dict[str, Any] = {"d": [23, 25, 27]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/sum_test.py b/tests/expr_and_series/sum_test.py index 6501869a49..dcf03f8723 100644 --- a/tests/expr_and_series/sum_test.py +++ b/tests/expr_and_series/sum_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").sum(), nw.sum("a", "b", "z")]) -def test_expr_sum_expr(constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(constructor(data)) +def test_expr_sum_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(expr) expected = {"a": [6], "b": [14], "z": [24.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_sum_expr(constructor: Constructor, expr: nw.Expr) -> None: @pytest.mark.parametrize(("col", "expected"), [("a", 6), ("b", 14), ("z", 24.0)]) def test_expr_sum_series( - constructor_eager: ConstructorEager, col: str, expected: float + nw_eager_constructor: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] result = series.sum() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/unary_test.py b/tests/expr_and_series/unary_test.py index 038136a902..50ee0c2e14 100644 --- a/tests/expr_and_series/unary_test.py +++ b/tests/expr_and_series/unary_test.py @@ -8,14 +8,14 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_unary(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "ibis" in str(constructor): +def test_unary(nw_frame_constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, None], "z": [7.0, 8.0, 9.0]} - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( a_mean=nw.col("a").mean(), a_median=nw.col("a").median(), a_sum=nw.col("a").sum(), @@ -40,9 +40,9 @@ def test_unary(constructor: Constructor, request: pytest.FixtureRequest) -> None assert_equal_data(result, expected) -def test_unary_series(constructor_eager: ConstructorEager) -> None: +def test_unary_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, None], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = { "a_mean": [df["a"].mean()], "a_median": [df["a"].median()], @@ -71,14 +71,14 @@ def test_unary_series(constructor_eager: ConstructorEager) -> None: def test_unary_two_elements( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2], "b": [2, 10], "c": [2.0, None]} - result = nw.from_native(constructor(data)).select( + result = nw.from_native(nw_frame_constructor(data)).select( a_nunique=nw.col("a").n_unique(), a_skew=nw.col("a").skew(), b_nunique=nw.col("b").n_unique(), @@ -97,9 +97,9 @@ def test_unary_two_elements( assert_equal_data(result, expected) -def test_unary_two_elements_series(constructor_eager: ConstructorEager) -> None: +def test_unary_two_elements_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2], "b": [2, 10], "c": [2.0, None]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = { "a_nunique": [df["a"].n_unique()], "a_skew": [df["a"].skew()], @@ -120,24 +120,26 @@ def test_unary_two_elements_series(constructor_eager: ConstructorEager) -> None: def test_unary_one_element( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): + if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( + nw_frame_constructor + ): request.applymarker(pytest.mark.xfail) - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1], "b": [2], "c": [None]} # Dask runs into a divide by zero RuntimeWarning for 1 element skew. context = ( pytest.warns(RuntimeWarning, match="invalid value encountered in scalar divide") - if "dask" in str(constructor) + if "dask" in str(nw_frame_constructor) else does_not_raise() ) result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_columns(nw.col("c").cast(nw.Float64)) .select( a_nunique=nw.col("a").n_unique(), @@ -160,9 +162,9 @@ def test_unary_one_element( assert_equal_data(result, expected) -def test_unary_one_element_series(constructor_eager: ConstructorEager) -> None: +def test_unary_one_element_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1], "b": [2], "c": [None]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = { "a_nunique": [df["a"].n_unique()], "a_skew": [df["a"].skew()], diff --git a/tests/expr_and_series/unique_test.py b/tests/expr_and_series/unique_test.py index c54a0356c7..fa2f482857 100644 --- a/tests/expr_and_series/unique_test.py +++ b/tests/expr_and_series/unique_test.py @@ -12,8 +12,8 @@ data_str = {"a": ["x", "x", "y", None]} -def test_unique_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_unique_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) context = ( pytest.raises((InvalidOperationError, NotImplementedError)) if isinstance(df, nw.LazyFrame) @@ -26,11 +26,11 @@ def test_unique_expr(constructor: Constructor) -> None: def test_unique_expr_agg( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("a").unique().sum()) expected = {"a": [3]} assert_equal_data(result, expected) @@ -39,16 +39,16 @@ def test_unique_expr_agg( assert_equal_data(result, expected) -def test_unique_illegal_combination(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_unique_illegal_combination(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.select((nw.col("a").unique() + nw.col("a").unique()).sum()) with pytest.raises((InvalidOperationError, NotImplementedError)): df.select(nw.col("a").unique() + nw.col("a")) -def test_unique_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data_str), eager_only=True)["a"] +def test_unique_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data_str), eager_only=True)["a"] result = series.unique(maintain_order=True) expected = {"a": ["x", "y", None]} assert_equal_data({"a": result}, expected) @@ -57,8 +57,8 @@ def test_unique_series(constructor_eager: ConstructorEager) -> None: assert_equal_data({"a": result}, expected) -def test_unique_series_numeric(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] +def test_unique_series_numeric(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.unique(maintain_order=True) expected = {"a": [1, None, 2]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/var_test.py b/tests/expr_and_series/var_test.py index f927dd1ac0..8bc9cad702 100644 --- a/tests/expr_and_series/var_test.py +++ b/tests/expr_and_series/var_test.py @@ -17,8 +17,10 @@ @pytest.mark.parametrize("input_data", [data, data_with_nulls]) -def test_var(constructor: Constructor, input_data: dict[str, list[float | None]]) -> None: - df = nw.from_native(constructor(input_data)) +def test_var( + nw_frame_constructor: Constructor, input_data: dict[str, list[float | None]] +) -> None: + df = nw.from_native(nw_frame_constructor(input_data)) result = df.select( nw.col("a").var(ddof=1).alias("a_ddof_1"), nw.col("a").var(ddof=0).alias("a_ddof_0"), @@ -38,9 +40,9 @@ def test_var(constructor: Constructor, input_data: dict[str, list[float | None]] @pytest.mark.parametrize("input_data", [data, data_with_nulls]) def test_var_series( - constructor_eager: ConstructorEager, input_data: dict[str, list[float | None]] + nw_eager_constructor: ConstructorEager, input_data: dict[str, list[float | None]] ) -> None: - df = nw.from_native(constructor_eager(input_data), eager_only=True) + df = nw.from_native(nw_eager_constructor(input_data), eager_only=True) result = { "a_ddof_1": [df["a"].var(ddof=1)], "a_ddof_0": [df["a"].var(ddof=0)], diff --git a/tests/expr_and_series/when_test.py b/tests/expr_and_series/when_test.py index aefac8492c..48eb103525 100644 --- a/tests/expr_and_series/when_test.py +++ b/tests/expr_and_series/when_test.py @@ -26,8 +26,8 @@ } -def test_when(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_when(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(value=3).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) @@ -36,15 +36,15 @@ def test_when(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_otherwise(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_when_otherwise(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(3).otherwise(6).alias("a_when")) expected = {"a_when": [3, 6, 6]} assert_equal_data(result, expected) -def test_multiple_conditions(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_multiple_conditions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.when(nw.col("a") < 3, nw.col("c") < 5.0).then(3).alias("a_when") ) @@ -52,45 +52,45 @@ def test_multiple_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_no_arg_when_fail(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_no_arg_when_fail(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((TypeError, ValueError)): df.select(nw.when().then(value=3).alias("a_when")) -def test_value_numpy_array(constructor_eager: ConstructorEager) -> None: +def test_value_numpy_array(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(np.arange(3, 6)).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) -def test_value_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_value_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) s_data = {"s": [3, 4, 5]} - s = nw.from_native(constructor_eager(s_data))["s"] + s = nw.from_native(nw_eager_constructor(s_data))["s"] assert isinstance(s, nw.Series) result = df.select(nw.when(nw.col("a") == 1).then(s).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) -def test_value_expression(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_value_expression(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(nw.col("a") + 9).alias("a_when")) expected = {"a_when": [10, None, None]} assert_equal_data(result, expected) -def test_otherwise_numpy_array(constructor_eager: ConstructorEager) -> None: +def test_otherwise_numpy_array(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) arr: _1DArray = np.zeros([3], np.dtype(np.int64)) arr[:3] = 0, 9, 10 @@ -99,18 +99,18 @@ def test_otherwise_numpy_array(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_otherwise_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_otherwise_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) s_data = {"s": [0, 9, 10]} - s = nw.from_native(constructor_eager(s_data))["s"] + s = nw.from_native(nw_eager_constructor(s_data))["s"] assert isinstance(s, nw.Series) result = df.select(nw.when(nw.col("a") == 1).then(-1).otherwise(s).alias("a_when")) expected = {"a_when": [-1, 9, 10]} assert_equal_data(result, expected) -def test_otherwise_expression(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_otherwise_expression(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select( nw.when(nw.col("a") == 1).then(-1).otherwise(nw.col("a") + 7).alias("a_when") ) @@ -118,17 +118,17 @@ def test_otherwise_expression(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_otherwise_into_expr(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_when_then_otherwise_into_expr(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a") > 1).then("c").otherwise("e")) expected = {"c": [7, 5, 6]} assert_equal_data(result, expected) -def test_when_then_broadcasting(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_when_then_broadcasting(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a").sum() > 1).then("c")) expected = {"c": [4.1, 5, 6]} assert_equal_data(result, expected) @@ -137,15 +137,15 @@ def test_when_then_broadcasting(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_otherwise_lit_str(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_when_then_otherwise_lit_str(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.when(nw.col("a") > 1).then(nw.col("b")).otherwise(nw.lit("z"))) expected = {"b": ["z", "b", "c"]} assert_equal_data(result, expected) -def test_when_then_otherwise_both_lit(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_when_then_otherwise_both_lit(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select( x1=nw.when(nw.col("a") > 1).then(nw.lit(42)).otherwise(nw.lit(-1)), x2=nw.when(nw.col("a") > 2).then(nw.lit(42)).otherwise(nw.lit(-1)), @@ -154,8 +154,8 @@ def test_when_then_otherwise_both_lit(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_otherwise_multi_output(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_when_then_otherwise_multi_output(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(x1=nw.when(nw.all() > 1).then(nw.col("a", "b"))) with pytest.raises(MultiOutputExpressionError): @@ -182,13 +182,13 @@ def test_when_then_otherwise_aggregate_select( then: nw.Expr | int, otherwise: nw.Expr | int | None, expected: list[int], - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "cudf" in str(constructor) and otherwise is None: + if "cudf" in str(nw_frame_constructor) and otherwise is None: reason = "cudf does not support mixed types" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) result = df.select(a_when=nw.when(condition).then(then).otherwise(otherwise)) assert_equal_data(result, {"a_when": expected}) @@ -213,30 +213,30 @@ def test_when_then_otherwise_aggregate_with_columns( then: nw.Expr | int, otherwise: nw.Expr | int | None, expected: list[int], - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "cudf" in str(constructor) and otherwise is None: + if "cudf" in str(nw_frame_constructor) and otherwise is None: reason = "cudf does not support mixed types" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) expr = nw.when(condition).then(then).otherwise(otherwise) result = df.with_columns(a_when=expr) assert_equal_data(result.select(nw.col("a_when")), {"a_when": expected}) -def test_when_then_empty(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [-1]})).filter(nw.col("a") > 0) +def test_when_then_empty(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [-1]})).filter(nw.col("a") > 0) result = df.with_columns(nw.when(nw.col("a") == 1).then(nw.lit(1)).alias("new_col")) expected: dict[str, Any] = {"a": [], "new_col": []} assert_equal_data(result, expected) -def test_when_chain_basic_two_conditions(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3]})) +def test_when_chain_basic_two_conditions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -251,8 +251,8 @@ def test_when_chain_basic_two_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_three_conditions(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_three_conditions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.when(nw.col("a") == 1) @@ -269,8 +269,8 @@ def test_when_chain_three_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_multiple_conditions(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) +def test_when_chain_multiple_conditions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") == 1) @@ -289,8 +289,8 @@ def test_when_chain_multiple_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_no_otherwise(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_no_otherwise(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.when(nw.col("a") == 1).then(10).when(nw.col("a") == 2).then(20).alias("result") @@ -300,8 +300,8 @@ def test_when_chain_no_otherwise(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_first_match_wins(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 5, 10]})) +def test_when_chain_first_match_wins(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 5, 10]})) result = df.select( nw.when(nw.col("a") < 5) @@ -318,8 +318,8 @@ def test_when_chain_first_match_wins(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_all_conditions_false(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3]})) +def test_when_chain_all_conditions_false(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") > 10) @@ -336,8 +336,8 @@ def test_when_chain_all_conditions_false(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_mixed_value_types(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_mixed_value_types(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.select( nw.when(nw.col("a") == 1) @@ -354,8 +354,10 @@ def test_when_chain_mixed_value_types(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_complex_conditions(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5], "b": [10, 20, 30, 40, 50]})) +def test_when_chain_complex_conditions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native( + nw_frame_constructor({"a": [1, 2, 3, 4, 5], "b": [10, 20, 30, 40, 50]}) + ) result = df.select( nw.when((nw.col("a") == 1) & (nw.col("b") == 10)) @@ -372,8 +374,8 @@ def test_when_chain_complex_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_with_nulls(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, None, 3, None, 5]})) +def test_when_chain_with_nulls(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, None, 3, None, 5]})) result = df.select( nw.when(nw.col("a") == 1) @@ -391,15 +393,17 @@ def test_when_chain_with_nulls(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_expression_conditions(constructor: Constructor) -> None: - if uses_pyarrow_backend(constructor) or "pyarrow" in str(constructor): +def test_when_chain_expression_conditions(nw_frame_constructor: Constructor) -> None: + if uses_pyarrow_backend(nw_frame_constructor) or "pyarrow" in str( + nw_frame_constructor + ): reason = ( "PyArrow backend doesn't support modulo operator. " "This is a pre-existing PyArrow arithmetic limitation." ) pytest.skip(reason=reason) - df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") % 2 == 0) @@ -420,8 +424,8 @@ def test_when_chain_expression_conditions(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_value_types_string(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": ["x", "y", "z"]})) +def test_when_chain_value_types_string(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": ["x", "y", "z"]})) result = df.select( nw.when(nw.col("a") == 1) @@ -436,8 +440,8 @@ def test_when_chain_value_types_string(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_value_types_float(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [1.1, 2.2, 3.3]})) +def test_when_chain_value_types_float(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [1.1, 2.2, 3.3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -454,8 +458,8 @@ def test_when_chain_value_types_float(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_value_types_mixed(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_value_types_mixed(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.select( nw.when(nw.col("a") == 1) @@ -472,8 +476,8 @@ def test_when_chain_value_types_mixed(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_with_columns(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_with_columns(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.with_columns( nw.when(nw.col("a") == 1) @@ -488,8 +492,8 @@ def test_when_chain_with_columns(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_multiple_columns(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3]})) +def test_when_chain_multiple_columns(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -511,9 +515,9 @@ def test_when_chain_multiple_columns(constructor: Constructor) -> None: def test_when_chain_backward_compatible_single_condition( - constructor: Constructor, + nw_frame_constructor: Constructor, ) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) # This is the existing API that must continue to work result = df.select(nw.when(nw.col("a") == 1).then(10).otherwise(20).alias("result")) @@ -522,8 +526,10 @@ def test_when_chain_backward_compatible_single_condition( assert_equal_data(result, expected) -def test_when_chain_two_conditions_no_otherwise(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) +def test_when_chain_two_conditions_no_otherwise( + nw_frame_constructor: Constructor, +) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") == 1).then(10).when(nw.col("a") == 2).then(20).alias("result") @@ -533,9 +539,13 @@ def test_when_chain_two_conditions_no_otherwise(constructor: Constructor) -> Non assert_equal_data(result, expected) -def test_when_chain_conditions_on_multiple_columns(constructor: Constructor) -> None: +def test_when_chain_conditions_on_multiple_columns( + nw_frame_constructor: Constructor, +) -> None: df = nw.from_native( - constructor({"a": [1, 2, 3, 4], "b": [10, 20, 30, 40], "c": [5, 15, 25, 35]}) + nw_frame_constructor( + {"a": [1, 2, 3, 4], "b": [10, 20, 30, 40], "c": [5, 15, 25, 35]} + ) ) result = df.select( @@ -555,8 +565,10 @@ def test_when_chain_conditions_on_multiple_columns(constructor: Constructor) -> assert_equal_data(result, expected) -def test_when_chain_boolean_column_condition(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [True, False, True, False], "b": [1, 2, 3, 4]})) +def test_when_chain_boolean_column_condition(nw_frame_constructor: Constructor) -> None: + df = nw.from_native( + nw_frame_constructor({"a": [True, False, True, False], "b": [1, 2, 3, 4]}) + ) result = df.select( nw.when(nw.col("a")) @@ -575,8 +587,8 @@ def test_when_chain_boolean_column_condition(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_branching_does_not_mutate(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_branching_does_not_mutate(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) base_expr = nw.when(nw.col("a") == 1).then(10) derived_expr = base_expr.when(nw.col("a") > 2).then(nw.col("a") * 10).otherwise(0) @@ -586,8 +598,10 @@ def test_when_chain_branching_does_not_mutate(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_composes_with_expr_operations(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) +def test_when_then_composes_with_expr_operations( + nw_frame_constructor: Constructor, +) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) result = df.select( ( diff --git a/tests/expression_parsing_test.py b/tests/expression_parsing_test.py index 138063eb06..028a652987 100644 --- a/tests/expression_parsing_test.py +++ b/tests/expression_parsing_test.py @@ -52,14 +52,14 @@ ], ) def test_over_pushdown( - constructor: Constructor, expr: nw.Expr, expected: list[float] + nw_frame_constructor: Constructor, expr: nw.Expr, expected: list[float] ) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [-1, 2, 3], "b": [1, 1, 2], "i": [0, 1, 2]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() result = df.select("i", a=expr).sort("i").select("a") assert_equal_data(result, {"a": expected}) @@ -68,18 +68,18 @@ def test_over_pushdown( ("expr", "expected"), [((nw.col("a") - nw.col("a").mean()).over("b"), [-1.5, 1.5, 0])] ) def test_per_group_broadcasting( - constructor: Constructor, + nw_frame_constructor: Constructor, expr: nw.Expr, expected: list[float], request: pytest.FixtureRequest, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # sigh... request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [-1, 2, 3], "b": [1, 1, 2], "i": [0, 1, 2]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() result = df.select("i", a=expr).sort("i").select("a") assert_equal_data(result, {"a": expected}) @@ -107,11 +107,13 @@ def test_per_group_broadcasting( nw.col("a").filter(nw.col("b").sum().over("c") > 1).sum().over("d"), ], ) -def test_invalid_operations(constructor: Constructor, expr: nw.Expr) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): +def test_invalid_operations(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() df = nw.from_native( - constructor({"a": [-1, 2, 3], "b": [1, 1, 1], "c": [2, 2, 2], "i": [0, 1, 2]}) + nw_frame_constructor( + {"a": [-1, 2, 3], "b": [1, 1, 1], "c": [2, 2, 2], "i": [0, 1, 2]} + ) ).lazy() with pytest.raises((InvalidOperationError, NotImplementedError)): df.select(a=expr) diff --git a/tests/frame/add_test.py b/tests/frame/add_test.py index 166be83fd6..9642aa48b8 100644 --- a/tests/frame/add_test.py +++ b/tests/frame/add_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_add(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_add(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns( c=nw.col("a") + nw.col("b"), d=nw.col("a") - nw.col("a").mean(), diff --git a/tests/frame/array_dunder_test.py b/tests/frame/array_dunder_test.py index d5db653c09..de17c855a1 100644 --- a/tests/frame/array_dunder_test.py +++ b/tests/frame/array_dunder_test.py @@ -16,55 +16,55 @@ def test_array_dunder( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) result = df.__array__() np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype="int64")) def test_array_dunder_with_dtype( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) result = df.__array__(object) np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype=object)) def test_array_dunder_with_copy( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < ( + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < ( 0, 20, 28, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) result = df.__array__(copy=True) np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype="int64")) - if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION < (3,): + if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < (3,): # If it's pandas, we know that `copy=False` definitely took effect. # So, let's check it! result = df.__array__(copy=False) diff --git a/tests/frame/clone_test.py b/tests/frame/clone_test.py index 66b9771835..ca0ecaf4d9 100644 --- a/tests/frame/clone_test.py +++ b/tests/frame/clone_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_clone(constructor_eager: ConstructorEager) -> None: +def test_clone(nw_eager_constructor: ConstructorEager) -> None: expected = {"a": [1, 2], "b": [3, 4]} expected_mod = {"a": [1, 2], "b": [3, 4], "c": [4, 6]} - df = nw.from_native(constructor_eager(expected), eager_only=True) + df = nw.from_native(nw_eager_constructor(expected), eager_only=True) df_clone = df.clone() assert df is not df_clone assert df._compliant_frame is not df_clone._compliant_frame diff --git a/tests/frame/collect_test.py b/tests/frame/collect_test.py index 66ea38e979..16085a709e 100644 --- a/tests/frame/collect_test.py +++ b/tests/frame/collect_test.py @@ -16,25 +16,25 @@ data = {"a": [1, 2], "b": [3, 4]} -def test_collect_to_default_backend(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_collect_to_default_backend(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect().to_native() expected_cls: Any - if "polars" in str(constructor): + if "polars" in str(nw_frame_constructor): pytest.importorskip("polars") import polars as pl expected_cls = pl.DataFrame - elif any(x in str(constructor) for x in ("pandas", "dask")): + elif any(x in str(nw_frame_constructor) for x in ("pandas", "dask")): pytest.importorskip("pandas") import pandas as pd expected_cls = pd.DataFrame - elif "modin" in str(constructor): + elif "modin" in str(nw_frame_constructor): mpd = get_modin() expected_cls = mpd.DataFrame - elif "cudf" in str(constructor): + elif "cudf" in str(nw_frame_constructor): cudf = get_cudf() expected_cls = cudf.DataFrame else: # pyarrow, duckdb, and PySpark @@ -51,13 +51,13 @@ def test_collect_to_default_backend(constructor: Constructor) -> None: ) @pytest.mark.parametrize("backend", ["pandas", Implementation.PANDAS]) def test_collect_to_valid_backend_pandas( - constructor: Constructor, backend: Pandas + nw_frame_constructor: Constructor, backend: Pandas ) -> None: pytest.importorskip("pandas") pytest.importorskip("pyarrow") import pandas as pd - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pd.DataFrame) @@ -67,13 +67,13 @@ def test_collect_to_valid_backend_pandas( ) @pytest.mark.parametrize("backend", ["polars", Implementation.POLARS]) def test_collect_to_valid_backend_polars( - constructor: Constructor, backend: Polars + nw_frame_constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") import polars as pl - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pl.DataFrame) @@ -83,12 +83,12 @@ def test_collect_to_valid_backend_polars( ) @pytest.mark.parametrize("backend", ["pyarrow", Implementation.PYARROW]) def test_collect_to_valid_backend_pyarrow( - constructor: Constructor, backend: Arrow + nw_frame_constructor: Constructor, backend: Arrow ) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pa.Table) @@ -96,12 +96,12 @@ def test_collect_to_valid_backend_pyarrow( @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_pandas_mod(constructor: Constructor) -> None: +def test_collect_to_valid_backend_pandas_mod(nw_frame_constructor: Constructor) -> None: pytest.importorskip("pandas") pytest.importorskip("pyarrow") import pandas as pd - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=pd).to_native() assert isinstance(result, pd.DataFrame) @@ -109,12 +109,12 @@ def test_collect_to_valid_backend_pandas_mod(constructor: Constructor) -> None: @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_polars_mod(constructor: Constructor) -> None: +def test_collect_to_valid_backend_polars_mod(nw_frame_constructor: Constructor) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") import polars as pl - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=pl).to_native() assert isinstance(result, pl.DataFrame) @@ -122,11 +122,11 @@ def test_collect_to_valid_backend_polars_mod(constructor: Constructor) -> None: @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_pyarrow_mod(constructor: Constructor) -> None: +def test_collect_to_valid_backend_pyarrow_mod(nw_frame_constructor: Constructor) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.lazy().collect(backend=pa).to_native() assert isinstance(result, pa.Table) @@ -135,15 +135,15 @@ def test_collect_to_valid_backend_pyarrow_mod(constructor: Constructor) -> None: "backend", ["foo", Implementation.DASK, Implementation.MODIN, pytest] ) def test_collect_to_invalid_backend( - constructor: Constructor, backend: Literal["foo"] | IntoBackend[Modin | Dask] + nw_frame_constructor: Constructor, backend: Literal["foo"] | IntoBackend[Modin | Dask] ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(ValueError, match="Unsupported `backend` value"): df.lazy().collect(backend=backend).to_native() # type: ignore[arg-type] -def test_collect_with_kwargs(constructor: Constructor) -> None: +def test_collect_with_kwargs(nw_frame_constructor: Constructor) -> None: pl_kwargs = ( {"optimizations": get_polars().QueryOptFlags(predicate_pushdown=False)} if POLARS_VERSION > (1, 29, 0) @@ -155,7 +155,7 @@ def test_collect_with_kwargs(constructor: Constructor) -> None: nw.Implementation.PYARROW: {}, } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.lazy() @@ -167,8 +167,8 @@ def test_collect_with_kwargs(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_collect_empty(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3]})) +def test_collect_empty(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) lf = df.filter(nw.col("a").is_null()).with_columns(b=nw.lit(None)).lazy() result = lf.collect() assert_equal_data(result, {"a": [], "b": []}) diff --git a/tests/frame/columns_test.py b/tests/frame/columns_test.py index 3fda986219..fd0eeca2f8 100644 --- a/tests/frame/columns_test.py +++ b/tests/frame/columns_test.py @@ -14,16 +14,16 @@ @pytest.mark.filterwarnings("ignore:Determining|Resolving.*") -def test_columns(constructor: Constructor) -> None: +def test_columns(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.columns expected = ["a", "b", "z"] assert result == expected -def test_iter_columns(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_iter_columns(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected = df.to_dict(as_series=True) result = {series.name: series for series in df.iter_columns()} diff --git a/tests/frame/concat_test.py b/tests/frame/concat_test.py index 00beb2ebc1..08a3d727e6 100644 --- a/tests/frame/concat_test.py +++ b/tests/frame/concat_test.py @@ -15,12 +15,12 @@ from collections.abc import Iterator -def test_concat_horizontal(constructor_eager: ConstructorEager) -> None: +def test_concat_horizontal(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_left = nw.from_native(constructor_eager(data), eager_only=True) + df_left = nw.from_native(nw_eager_constructor(data), eager_only=True) data_right = {"c": [6, 12, -1], "d": [0, -4, 2]} - df_right = nw.from_native(constructor_eager(data_right), eager_only=True) + df_right = nw.from_native(nw_eager_constructor(data_right), eager_only=True) result = nw.concat([df_left, df_right], how="horizontal") expected = { @@ -39,14 +39,17 @@ def test_concat_horizontal(constructor_eager: ConstructorEager) -> None: nw.concat([df_left.lazy()], how="horizontal") -def test_concat_vertical(constructor: Constructor) -> None: +def test_concat_vertical(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} df_left = ( - nw.from_native(constructor(data)).lazy().rename({"a": "c", "b": "d"}).drop("z") + nw.from_native(nw_frame_constructor(data)) + .lazy() + .rename({"a": "c", "b": "d"}) + .drop("z") ) data_right = {"c": [6, 12, -1], "d": [0, -4, 2]} - df_right = nw.from_native(constructor(data_right)).lazy() + df_right = nw.from_native(nw_frame_constructor(data_right)).lazy() result = nw.concat([df_left, df_right], how="vertical") expected = {"c": [1, 3, 2, 6, 12, -1], "d": [4, 4, 6, 0, -4, 2]} @@ -67,7 +70,7 @@ def test_concat_vertical(constructor: Constructor) -> None: nw.concat([df_left, df_left.select("d")], how="vertical").collect() -def test_concat_diagonal(constructor: Constructor) -> None: +def test_concat_diagonal(nw_frame_constructor: Constructor) -> None: data_1 = {"a": [1, 3], "b": [4, 6]} data_2 = {"a": [100, 200], "z": ["x", "y"]} expected = { @@ -76,8 +79,8 @@ def test_concat_diagonal(constructor: Constructor) -> None: "z": [None, None, "x", "y"], } - df_1 = nw.from_native(constructor(data_1)).lazy() - df_2 = nw.from_native(constructor(data_2)).lazy() + df_1 = nw.from_native(nw_frame_constructor(data_1)).lazy() + df_2 = nw.from_native(nw_frame_constructor(data_2)).lazy() result = nw.concat([df_1, df_2], how="diagonal") @@ -88,12 +91,12 @@ def test_concat_diagonal(constructor: Constructor) -> None: def _from_natives( - constructor: Constructor, *sources: dict[str, list[Any]] + nw_frame_constructor: Constructor, *sources: dict[str, list[Any]] ) -> Iterator[nw.LazyFrame[Any]]: - yield from (nw.from_native(constructor(data)).lazy() for data in sources) + yield from (nw.from_native(nw_frame_constructor(data)).lazy() for data in sources) -def test_concat_diagonal_bigger(constructor: Constructor) -> None: +def test_concat_diagonal_bigger(nw_frame_constructor: Constructor) -> None: # NOTE: `ibis.union` doesn't guarantee the order of outputs # https://github.com/narwhals-dev/narwhals/pull/3404#discussion_r2694556781 data_1 = {"idx": [1, 2], "a": [1, 2], "b": [3, 4]} @@ -105,13 +108,13 @@ def test_concat_diagonal_bigger(constructor: Constructor) -> None: "b": [3, 4, None, None, 9, 10], "c": [None, None, 7, 8, 11, 12], } - dfs = _from_natives(constructor, data_1, data_2, data_3) + dfs = _from_natives(nw_frame_constructor, data_1, data_2, data_3) result = nw.concat(dfs, how="diagonal").sort("idx") assert_equal_data(result, expected) def test_concat_diagonal_invalid( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: data_1 = {"a": [1, 3], "b": [4, 6]} data_2 = { @@ -119,8 +122,8 @@ def test_concat_diagonal_invalid( "b": [4, 6], "z": ["x", "y"], } - df_1 = nw.from_native(constructor(data_1)).lazy() - bad_schema = nw.from_native(constructor(data_2)).lazy() + df_1 = nw.from_native(nw_frame_constructor(data_1)).lazy() + bad_schema = nw.from_native(nw_frame_constructor(data_2)).lazy() impl = df_1.implementation request.applymarker( pytest.mark.xfail( diff --git a/tests/frame/double_test.py b/tests/frame/double_test.py index 6a8f5d6333..52901cf196 100644 --- a/tests/frame/double_test.py +++ b/tests/frame/double_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, assert_equal_data -def test_double(constructor: Constructor) -> None: +def test_double(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0]} diff --git a/tests/frame/drop_nulls_test.py b/tests/frame/drop_nulls_test.py index 34d433979d..dd289f455d 100644 --- a/tests/frame/drop_nulls_test.py +++ b/tests/frame/drop_nulls_test.py @@ -8,8 +8,8 @@ data = {"alpha": [1.0, 2.0, None, 4.0], "beta gamma": [None, 3.0, None, 5.0]} -def test_drop_nulls(constructor: Constructor) -> None: - result = nw.from_native(constructor(data)).drop_nulls() +def test_drop_nulls(nw_frame_constructor: Constructor) -> None: + result = nw.from_native(nw_frame_constructor(data)).drop_nulls() expected = {"alpha": [2.0, 4.0], "beta gamma": [3.0, 5.0]} assert_equal_data(result, expected) @@ -23,7 +23,7 @@ def test_drop_nulls(constructor: Constructor) -> None: ], ) def test_drop_nulls_subset( - constructor: Constructor, subset: str | list[str], expected: dict[str, float] + nw_frame_constructor: Constructor, subset: str | list[str], expected: dict[str, float] ) -> None: - result = nw.from_native(constructor(data)).drop_nulls(subset=subset) + result = nw.from_native(nw_frame_constructor(data)).drop_nulls(subset=subset) assert_equal_data(result, expected) diff --git a/tests/frame/drop_test.py b/tests/frame/drop_test.py index 233ab3003b..4d018a5a8d 100644 --- a/tests/frame/drop_test.py +++ b/tests/frame/drop_test.py @@ -17,9 +17,11 @@ ("to_drop", "expected"), [("abc", ["b", "z"]), (["abc"], ["b", "z"]), (["abc", "b"], ["z"])], ) -def test_drop(constructor: Constructor, to_drop: list[str], expected: list[str]) -> None: +def test_drop( + nw_frame_constructor: Constructor, to_drop: list[str], expected: list[str] +) -> None: data = {"abc": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) assert df.drop(to_drop).collect_schema().names() == expected if not isinstance(to_drop, str): assert df.drop(*to_drop).collect_schema().names() == expected @@ -27,19 +29,23 @@ def test_drop(constructor: Constructor, to_drop: list[str], expected: list[str]) @pytest.mark.parametrize("strict", [True, False]) def test_drop_strict( - request: pytest.FixtureRequest, constructor: Constructor, *, strict: bool + request: pytest.FixtureRequest, nw_frame_constructor: Constructor, *, strict: bool ) -> None: - if "polars_lazy" in str(constructor) and POLARS_VERSION < (1, 0, 0) and strict: + if ( + "polars_lazy" in str(nw_frame_constructor) + and POLARS_VERSION < (1, 0, 0) + and strict + ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6]} to_drop = ["a", "z"] - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) context: Any if strict: - if "polars_lazy" in str(constructor): + if "polars_lazy" in str(nw_frame_constructor): msg = r"^(\"z\"|z)" else: msg = ( diff --git a/tests/frame/eq_test.py b/tests/frame/eq_test.py index c100469451..92223a397d 100644 --- a/tests/frame/eq_test.py +++ b/tests/frame/eq_test.py @@ -10,8 +10,8 @@ from tests.utils import Constructor -def test_eq_neq_raise(constructor: Constructor) -> None: +def test_eq_neq_raise(nw_frame_constructor: Constructor) -> None: with pytest.raises(NotImplementedError, match="please use expressions"): - nw.from_native(constructor({"a": [1, 2, 3]})) == 0 # noqa: B015 + nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) == 0 # noqa: B015 with pytest.raises(NotImplementedError, match="please use expressions"): - nw.from_native(constructor({"a": [1, 2, 3]})) != 0 # noqa: B015 + nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) != 0 # noqa: B015 diff --git a/tests/frame/estimated_size_test.py b/tests/frame/estimated_size_test.py index 78c1cc86f7..e55f6276ac 100644 --- a/tests/frame/estimated_size_test.py +++ b/tests/frame/estimated_size_test.py @@ -13,8 +13,8 @@ data = {"a": list(range(100))} -def test_estimated_size(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_estimated_size(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert df.estimated_size("b") > 0 assert df.estimated_size("kb") == (df.estimated_size("b") / 1024) diff --git a/tests/frame/explode_test.py b/tests/frame/explode_test.py index 596eaa82a9..3b46c627c9 100644 --- a/tests/frame/explode_test.py +++ b/tests/frame/explode_test.py @@ -31,20 +31,23 @@ ) def test_explode_single_col( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, column: str, expected_values: list[int | None], ) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf", "pyarrow_table")): + if any( + backend in str(nw_frame_constructor) + for backend in ("dask", "cudf", "pyarrow_table") + ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_columns(nw.col(column).cast(nw.List(nw.Int32()))) .explode(column) .select("a", column) @@ -79,24 +82,24 @@ def test_explode_single_col( ) def test_explode_multiple_cols( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, column: str, more_columns: Sequence[str], expected: dict[str, list[str | int | None]], ) -> None: if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("dask", "cudf", "pyarrow_table", "duckdb", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_columns(nw.col(column, *more_columns).cast(nw.List(nw.Int32()))) .explode(column, *more_columns) .select("a", column, *more_columns) @@ -106,12 +109,15 @@ def test_explode_multiple_cols( def test_explode_shape_error( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(backend in str(constructor) for backend in ("dask", "cudf", "pyarrow_table")): + if any( + backend in str(nw_frame_constructor) + for backend in ("dask", "cudf", "pyarrow_table") + ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") @@ -121,7 +127,7 @@ def test_explode_shape_error( match=r".*exploded columns (must )?have matching element counts", ): _ = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .lazy() .with_columns(nw.col("l1", "l2", "l3").cast(nw.List(nw.Int32()))) .explode("l1", "l3") @@ -130,15 +136,15 @@ def test_explode_shape_error( def test_explode_invalid_operation_error( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "dask")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 6): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 6): pytest.skip() with pytest.raises( InvalidOperationError, match="`explode` operation not supported for dtype" ): - _ = nw.from_native(constructor(data)).lazy().explode("a").collect() + _ = nw.from_native(nw_frame_constructor(data)).lazy().explode("a").collect() diff --git a/tests/frame/filter_test.py b/tests/frame/filter_test.py index f8048d8e4c..80a0505050 100644 --- a/tests/frame/filter_test.py +++ b/tests/frame/filter_test.py @@ -19,17 +19,17 @@ ], ) def test_filter_with_expr_predicates( - constructor: Constructor, + nw_frame_constructor: Constructor, predicates: tuple[nw.Expr, ...], expected: dict[str, list[Any]], ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.filter(*predicates) assert_equal_data(result, expected) -def test_filter_with_series_predicates(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_filter_with_series_predicates(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.filter(df["a"] > 1) expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9.0]} assert_equal_data(result, expected) @@ -47,11 +47,11 @@ def test_filter_with_series_predicates(constructor_eager: ConstructorEager) -> N ], ) def test_filter_with_boolean_list_predicates_eager( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, predicates: tuple[list[bool], ...], expected: dict[str, list[Any]], ) -> None: - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.filter(*predicates) assert_equal_data(result, expected) @@ -66,27 +66,27 @@ def test_filter_with_boolean_list_predicates_eager( ], ) def test_filter_with_boolean_list_predicates_lazy( - constructor: Constructor, predicates: tuple[list[bool] | nw.Expr, ...] + nw_frame_constructor: Constructor, predicates: tuple[list[bool] | nw.Expr, ...] ) -> None: - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() with pytest.raises(TypeError, match="not supported with Python boolean masks"): df.filter(*predicates) # type: ignore[arg-type] -def test_filter_raise_on_agg_predicate(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_filter_raise_on_agg_predicate(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(InvalidOperationError): df.filter(nw.col("a").max() > 2).lazy().collect() -def test_filter_raise_on_shape_mismatch(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_filter_raise_on_shape_mismatch(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.filter(nw.col("b").unique() > 2).lazy().collect() -def test_filter_with_constrains_only(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_filter_with_constrains_only(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result_scalar = df.filter(a=3) expected_scalar = {"a": [3], "b": [4], "z": [8.0]} @@ -99,14 +99,14 @@ def test_filter_with_constrains_only(constructor: Constructor) -> None: def test_filter_missing_column( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "pyspark[connect]", "ibis")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) - if "polars" in str(constructor): + df = nw.from_native(nw_frame_constructor(data)) + if "polars" in str(nw_frame_constructor): msg = r"unable to find column \"c\"; valid columns: \[\"a\", \"b\"\, \"z\"\]" elif any(id_ == constructor_id for id_ in ("duckdb", "pyspark")): msg = r"\n\nHint: Did you mean one of these columns: \['a', 'b', 'z'\]?" @@ -116,7 +116,7 @@ def test_filter_missing_column( r"\n\nHint: Did you mean one of these columns: \['a', 'b', 'z'\]?" ) - if "polars_lazy" in str(constructor) and isinstance(df, nw.LazyFrame): + if "polars_lazy" in str(nw_frame_constructor) and isinstance(df, nw.LazyFrame): with pytest.raises(ColumnNotFoundError, match=msg): df.filter(c=5).collect() else: @@ -125,10 +125,10 @@ def test_filter_missing_column( def test_filter_with_predicates_and_constraints( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, ) -> None: # Adapted from https://github.com/narwhals-dev/narwhals/pull/3173/commits/8433b2d75438df98004a3c850ad23628e2376836 - df = nw.from_native(constructor_eager({"a": range(5), "b": [2, 2, 4, 2, 4]})) + df = nw.from_native(nw_eager_constructor({"a": range(5), "b": [2, 2, 4, 2, 4]})) mask = [True, False, True, True, False] mask_2 = [True, True, False, True, False] expected_mask_only = {"a": [0, 2, 3], "b": [2, 4, 2]} @@ -139,7 +139,7 @@ def test_filter_with_predicates_and_constraints( msg = ( r"unable to find column \"c\"; valid columns: \[\"a\", \"b\"\]" - if "polars" in str(constructor_eager) + if "polars" in str(nw_eager_constructor) else ( r"The following columns were not found: \[.*\]" r"\n\nHint: Did you mean one of these columns: \['a', 'b'\]?" @@ -167,10 +167,12 @@ def test_filter_with_predicates_and_constraints( assert_equal_data(result, expected_mixed) -def test_filter_multiple_predicates(constructor: Constructor) -> None: +def test_filter_multiple_predicates(nw_frame_constructor: Constructor) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L175-L202.""" df = nw.from_native( - constructor({"a": [1, 1, 1, 2, 2], "b": [1, 1, 2, 2, 2], "c": [1, 1, 2, 3, 4]}) + nw_frame_constructor( + {"a": [1, 1, 1, 2, 2], "b": [1, 1, 2, 2, 2], "c": [1, 1, 2, 3, 4]} + ) ) # multiple predicates @@ -190,10 +192,12 @@ def test_filter_multiple_predicates(constructor: Constructor) -> None: ) -def test_filter_string_predicate(constructor: Constructor) -> None: +def test_filter_string_predicate(nw_frame_constructor: Constructor) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L204-L210.""" df = nw.from_native( - constructor({"description": ["eq", "gt", "ge"], "predicate": ["==", ">", ">="]}) + nw_frame_constructor( + {"description": ["eq", "gt", "ge"], "predicate": ["==", ">", ">="]} + ) ) expected = {"description": ["eq"], "predicate": ["=="]} result = df.filter(predicate="==") @@ -203,9 +207,11 @@ def test_filter_string_predicate(constructor: Constructor) -> None: @pytest.mark.parametrize( "predicates", [(nw.col("z") < 10,), (nw.col("a") > 0, nw.col("b") > 0)] ) -def test_filter_seq_iterable_all_true(constructor: Constructor, predicates: Any) -> None: +def test_filter_seq_iterable_all_true( + nw_frame_constructor: Constructor, predicates: Any +) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L213-L233.""" - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) predicate = (p for p in predicates) assert_equal_data(df.filter(predicate), data) @@ -213,8 +219,10 @@ def test_filter_seq_iterable_all_true(constructor: Constructor, predicates: Any) @pytest.mark.parametrize( "predicates", [(nw.col("z") > 10,), (nw.col("a") < 0, nw.col("b") < 0)] ) -def test_filter_seq_iterable_all_false(constructor: Constructor, predicates: Any) -> None: - df = nw.from_native(constructor(data)) +def test_filter_seq_iterable_all_false( + nw_frame_constructor: Constructor, predicates: Any +) -> None: + df = nw.from_native(nw_frame_constructor(data)) expected: dict[str, list[Any]] = {"a": [], "b": [], "z": []} predicate = (p for p in predicates) assert_equal_data(df.filter(predicate), expected) diff --git a/tests/frame/from_dict_test.py b/tests/frame/from_dict_test.py index 4378d9820f..028eb326ff 100644 --- a/tests/frame/from_dict_test.py +++ b/tests/frame/from_dict_test.py @@ -28,12 +28,14 @@ def test_from_dict_schema(eager_backend: EagerAllowed) -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) -def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> None: +def test_from_dict_without_backend( + nw_frame_constructor: Constructor, backend: Polars +) -> None: pytest.importorskip("polars") pytest.importorskip("pyarrow") df = ( - nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) @@ -41,8 +43,12 @@ def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> assert_equal_data(result, {"c": [1, 2, 3], "d": [4, 5, 6]}) -def test_from_dict_without_backend_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).lazy().collect() +def test_from_dict_without_backend_invalid(nw_frame_constructor: Constructor) -> None: + df = ( + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + .lazy() + .collect() + ) with pytest.raises(TypeError, match="backend"): nw.DataFrame.from_dict({"c": nw.to_native(df["a"]), "d": nw.to_native(df["b"])}) @@ -55,13 +61,13 @@ def test_from_dict_with_backend_invalid() -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) def test_from_dict_one_native_one_narwhals( - constructor: Constructor, backend: Polars + nw_frame_constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") df = ( - nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) diff --git a/tests/frame/get_column_test.py b/tests/frame/get_column_test.py index 83c4943342..ce4e31070d 100644 --- a/tests/frame/get_column_test.py +++ b/tests/frame/get_column_test.py @@ -6,8 +6,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_get_column(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [1, 2], "b": [3, 4]}), eager_only=True) +def test_get_column(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, 2], "b": [3, 4]}), eager_only=True) result = df.get_column("a") assert_equal_data({"a": result}, {"a": [1, 2]}) assert result.name == "a" diff --git a/tests/frame/getitem_test.py b/tests/frame/getitem_test.py index c079d154bb..deabecab73 100644 --- a/tests/frame/getitem_test.py +++ b/tests/frame/getitem_test.py @@ -17,26 +17,26 @@ } -def test_slice_column(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager(data))["a"] +def test_slice_column(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native(nw_eager_constructor(data))["a"] assert isinstance(result, nw.Series) assert_equal_data({"a": result}, {"a": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]}) -def test_slice_rows(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager(data))[1:] +def test_slice_rows(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native(nw_eager_constructor(data))[1:] assert_equal_data(result, {"a": [2.0, 3.0, 4.0, 5.0, 6.0], "b": [12, 13, 14, 15, 16]}) - result = nw.from_native(constructor_eager(data))[2:4] + result = nw.from_native(nw_eager_constructor(data))[2:4] assert_equal_data(result, {"a": [3.0, 4.0], "b": [13, 14]}) def test_slice_rows_with_step( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - result = nw.from_native(constructor_eager(data))[1::2] + result = nw.from_native(nw_eager_constructor(data))[1::2] assert_equal_data(result, {"a": [2.0, 4.0, 6.0], "b": [12, 14, 16]}) @@ -62,23 +62,23 @@ def test_slice_lazy_fails() -> None: _ = nw.from_native(pl.LazyFrame(data))[1:] -def test_slice_int(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager(data), eager_only=True)[1] +def test_slice_int(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native(nw_eager_constructor(data), eager_only=True)[1] assert_equal_data(result, {"a": [2], "b": [12]}) -def test_slice_fails(constructor_eager: ConstructorEager) -> None: +def test_slice_fails(nw_eager_constructor: ConstructorEager) -> None: class Foo: ... with pytest.raises(TypeError, match=r"Unexpected type.*, got:"): - nw.from_native(constructor_eager(data), eager_only=True)[Foo()] # type: ignore[call-overload, unused-ignore] + nw.from_native(nw_eager_constructor(data), eager_only=True)[Foo()] # type: ignore[call-overload, unused-ignore] -def test_gather(constructor_eager: ConstructorEager) -> None: +def test_gather(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df[[0, 3, 1]] expected = {"a": [1.0, 4.0, 2.0], "b": [11, 14, 12]} assert_equal_data(result, expected) @@ -102,11 +102,11 @@ def test_gather_pandas_index() -> None: assert_equal_data(result, expected) -def test_gather_rows_cols(constructor_eager: ConstructorEager) -> None: +def test_gather_rows_cols(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - native_df = constructor_eager(data) + native_df = nw_eager_constructor(data) df = nw.from_native(native_df, eager_only=True) expected = {"b": [11, 14, 12]} @@ -118,30 +118,30 @@ def test_gather_rows_cols(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_slice_both_list_of_ints(constructor_eager: ConstructorEager) -> None: +def test_slice_both_list_of_ints(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df[[0, 1], [0, 2]] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) def test_slice_both_tuple( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # https://github.com/rapidsai/cudf/issues/18556 request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df[(0, 1), ("a", "c")] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) -def test_slice_int_rows_str_columns(constructor_eager: ConstructorEager) -> None: +def test_slice_int_rows_str_columns(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df[[0, 1], ["a", "c"]] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) @@ -178,26 +178,26 @@ def test_slice_int_rows_str_columns(constructor_eager: ConstructorEager) -> None ], ) def test_slice_slice_columns( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, row_selector: Any, col_selector: Any, expected: dict[str, list[Any]], ) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df[row_selector] if col_selector is None else df[row_selector, col_selector] assert_equal_data(result, expected) -def test_slice_item(constructor_eager: ConstructorEager) -> None: +def test_slice_item(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2], "b": [4, 5]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert df[0, 0] == 1 -def test_slice_edge_cases(constructor_eager: ConstructorEager) -> None: +def test_slice_edge_cases(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert df[[], :].shape == (0, 4) assert df[:, []].shape == (0, 0) assert df[[]].shape == (0, 4) @@ -219,11 +219,11 @@ def test_slice_edge_cases(constructor_eager: ConstructorEager) -> None: ], ) def test_get_item_works_with_tuple_and_list_and_range_row_and_col_indexing( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, row_idx: list[int] | tuple[int] | range, col_idx: list[int] | tuple[int] | range, ) -> None: - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) nw_df[row_idx, col_idx] @@ -231,11 +231,11 @@ def test_get_item_works_with_tuple_and_list_and_range_row_and_col_indexing( ("row_idx", "col"), [([0, 2], slice(1)), ((0, 2), slice(1)), (range(2), slice(1))] ) def test_get_item_works_with_tuple_and_list_and_range_row_indexing_and_slice_col_indexing( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, row_idx: list[int] | tuple[int] | range, col: slice, ) -> None: - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) nw_df[row_idx, col] @@ -243,42 +243,44 @@ def test_get_item_works_with_tuple_and_list_and_range_row_indexing_and_slice_col ("row_idx", "col"), [([0, 2], "a"), ((0, 2), "a"), (range(2), "a")] ) def test_get_item_works_with_tuple_and_list_indexing_and_str( - constructor_eager: ConstructorEager, row_idx: list[int] | tuple[int] | range, col: str + nw_eager_constructor: ConstructorEager, + row_idx: list[int] | tuple[int] | range, + col: str, ) -> None: - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) nw_df[row_idx, col] -def test_getitem_ndarray_columns(constructor_eager: ConstructorEager) -> None: +def test_getitem_ndarray_columns(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) arr = np.arange(2) result = nw_df[:, arr] expected = {"col1": ["a", "b", "c", "d"], "col2": [0, 1, 2, 3]} assert_equal_data(result, expected) -def test_getitem_ndarray_columns_labels(constructor_eager: ConstructorEager) -> None: +def test_getitem_ndarray_columns_labels(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) arr: np.ndarray[tuple[int], np.dtype[Any]] = np.array(["col1", "col2"]) # pyright: ignore[reportAssignmentType] result = nw_df[:, arr] expected = {"col1": ["a", "b", "c", "d"], "col2": [0, 1, 2, 3]} assert_equal_data(result, expected) -def test_getitem_negative_slice(constructor_eager: ConstructorEager) -> None: +def test_getitem_negative_slice(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = nw_df[-3:-2, ["col3", "col1"]] expected = {"col3": [3], "col1": ["b"]} assert_equal_data(result, expected) @@ -290,20 +292,20 @@ def test_getitem_negative_slice(constructor_eager: ConstructorEager) -> None: assert_equal_data({"col1": result_s}, expected) -def test_zeroth_row_no_columns(constructor_eager: ConstructorEager) -> None: +def test_zeroth_row_no_columns(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) columns: list[str] = [] result = nw_df[0, columns] assert result.shape == (0, 0) -def test_single_tuple(constructor_eager: ConstructorEager) -> None: +def test_single_tuple(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) # Technically works but we should probably discourage it # OK if overloads don't match it. result = nw_df[[0, 1],] # type: ignore[index] @@ -311,23 +313,23 @@ def test_single_tuple(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_triple_tuple(constructor_eager: ConstructorEager) -> None: +def test_triple_tuple(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3]} with pytest.raises(TypeError, match="Tuples cannot"): - nw.from_native(constructor_eager(data), eager_only=True)[(1, 2, 3)] + nw.from_native(nw_eager_constructor(data), eager_only=True)[(1, 2, 3)] def test_slice_with_series( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: request.applymarker( pytest.mark.xfail( - "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (3,), + "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (3,), reason="https://github.com/pandas-dev/pandas/issues/61311", ) ) data = {"a": [1, 2, 3], "c": [0, 2, 1]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = nw_df[nw_df["c"]] expected = {"a": [1, 3, 2], "c": [0, 1, 2]} assert_equal_data(result, expected) @@ -336,32 +338,32 @@ def test_slice_with_series( assert_equal_data(result, expected) -def test_horizontal_slice_with_series(constructor_eager: ConstructorEager) -> None: +def test_horizontal_slice_with_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2], "c": [0, 2], "d": ["c", "a"]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = nw_df[nw_df["d"]] expected = {"c": [0, 2], "a": [1, 2]} assert_equal_data(result, expected) def test_horizontal_slice_with_series_2( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: request.applymarker( pytest.mark.xfail( - "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (3,), + "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (3,), reason="https://github.com/pandas-dev/pandas/issues/61311", ) ) data = {"a": [1, 2], "c": [0, 2], "d": ["c", "a"]} - nw_df = nw.from_native(constructor_eager(data), eager_only=True) + nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = nw_df[:, nw_df["c"]] expected = {"a": [1, 2], "d": ["c", "a"]} assert_equal_data(result, expected) -def test_native_slice_series(constructor_eager: ConstructorEager) -> None: - s = nw.from_native(constructor_eager({"a": [0, 2, 1]}), eager_only=True)["a"] +def test_native_slice_series(nw_eager_constructor: ConstructorEager) -> None: + s = nw.from_native(nw_eager_constructor({"a": [0, 2, 1]}), eager_only=True)["a"] result = {"a": s[s.to_native()]} expected = {"a": [0, 1, 2]} assert_equal_data(result, expected) @@ -383,18 +385,18 @@ def test_pandas_non_str_columns() -> None: assert result.to_dict(as_series=False) == expected -def test_select_rows_by_name(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [0, 2, 1]}), eager_only=True) +def test_select_rows_by_name(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [0, 2, 1]}), eager_only=True) with pytest.raises(TypeError, match="Unexpected type"): df["a", :] # type: ignore[index] -def test_getitem_boolean_columns(constructor_eager: ConstructorEager) -> None: +def test_getitem_boolean_columns(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np df = nw.from_native( - constructor_eager({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), + nw_eager_constructor({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), eager_only=True, ) result = df[:, [False, True, True]] @@ -406,9 +408,9 @@ def test_getitem_boolean_columns(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_getitem_single_boolean_column(constructor_eager: ConstructorEager) -> None: +def test_getitem_single_boolean_column(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), + nw_eager_constructor({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), eager_only=True, ) with pytest.raises(TypeError): diff --git a/tests/frame/group_by_test.py b/tests/frame/group_by_test.py index 788a5363a4..202b4fbce4 100644 --- a/tests/frame/group_by_test.py +++ b/tests/frame/group_by_test.py @@ -73,8 +73,8 @@ def test_invalid_group_by_dask() -> None: nw.from_native(df_dask).group_by("a").agg(nw.col("b").abs().min()) -def test_group_by_iter(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_group_by_iter(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) expected_keys = [(1,), (3,)] keys = [] for key, sub_df in df.group_by("a"): @@ -108,8 +108,10 @@ def test_group_by_iter_non_str_pandas() -> None: assert_equal_data(groups, expected) -def test_group_by_nw_all(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 8, 9]})) +def test_group_by_nw_all(nw_frame_constructor: Constructor) -> None: + df = nw.from_native( + nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 8, 9]}) + ) result = df.group_by("a").agg(nw.all().sum()).sort("a") expected = {"a": [1, 2], "b": [9, 6], "c": [15, 9]} assert_equal_data(result, expected) @@ -133,17 +135,21 @@ def test_group_by_nw_all(constructor: Constructor) -> None: ], ) def test_group_by_depth_1_agg( - constructor: Constructor, attr: str, expected: dict[str, list[int | float]] + nw_frame_constructor: Constructor, attr: str, expected: dict[str, list[int | float]] ) -> None: - if "pandas_pyarrow" in str(constructor) and attr == "var" and PANDAS_VERSION < (2, 1): + if ( + "pandas_pyarrow" in str(nw_frame_constructor) + and attr == "var" + and PANDAS_VERSION < (2, 1) + ): pytest.skip( "Known issue with variance calculation in pandas 2.0.x with pyarrow backend in groupby operations" ) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 1, 2], "b": [1, None, 2, 3]} expr = getattr(nw.col("b"), attr)() - result = nw.from_native(constructor(data)).group_by("a").agg(expr).sort("a") + result = nw.from_native(nw_frame_constructor(data)).group_by("a").agg(expr).sort("a") assert_equal_data(result, expected) @@ -163,16 +169,18 @@ def test_group_by_depth_1_agg( ) def test_group_by_depth_1_agg_bool_ops( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, values: dict[str, list[bool]], expected: dict[str, list[bool]], ) -> None: - if ("dask-nullable" in request.node.callspec.id) or ("cudf" in str(constructor)): + if ("dask-nullable" in request.node.callspec.id) or ( + "cudf" in str(nw_frame_constructor) + ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 2, 3, 3], **values} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("a") .agg(nw.col("x").all().alias("all"), nw.col("x").any().alias("any")) .sort("a") @@ -183,7 +191,9 @@ def test_group_by_depth_1_agg_bool_ops( @pytest.mark.parametrize( ("attr", "ddof"), [("std", 0), ("var", 0), ("std", 2), ("var", 2)] ) -def test_group_by_depth_1_std_var(constructor: Constructor, attr: str, ddof: int) -> None: +def test_group_by_depth_1_std_var( + nw_frame_constructor: Constructor, attr: str, ddof: int +) -> None: data = {"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]} _pow = 0.5 if attr == "std" else 1 expected = { @@ -194,14 +204,14 @@ def test_group_by_depth_1_std_var(constructor: Constructor, attr: str, ddof: int ], } expr = getattr(nw.col("b"), attr)(ddof=ddof) - result = nw.from_native(constructor(data)).group_by("a").agg(expr).sort("a") + result = nw.from_native(nw_frame_constructor(data)).group_by("a").agg(expr).sort("a") assert_equal_data(result, expected) -def test_group_by_median(constructor: Constructor) -> None: +def test_group_by_median(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 1, 1, 2, 2, 2], "b": [5, 4, 6, 7, 3, 2]} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("a") .agg(nw.col("b").median()) .sort("a") @@ -210,12 +220,12 @@ def test_group_by_median(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_group_by_n_unique_w_missing(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_group_by_n_unique_w_missing(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [4, None, 5], "c": [None, None, 7], "d": [1, 1, 3]} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("a") .agg( nw.col("b").n_unique(), @@ -259,9 +269,9 @@ def test_group_by_empty_result_pandas() -> None: ) -def test_group_by_simple_named(constructor: Constructor) -> None: +def test_group_by_simple_named(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 2, 1]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() result = ( df.group_by("a").agg(b_min=nw.col("b").min(), b_max=nw.col("b").max()).sort("a") ) @@ -269,17 +279,17 @@ def test_group_by_simple_named(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_group_by_simple_unnamed(constructor: Constructor) -> None: +def test_group_by_simple_unnamed(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 2, 1]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() result = df.group_by("a").agg(nw.col("b").min(), nw.col("c").max()).sort("a") expected = {"a": [1, 2], "b": [4, 6], "c": [7, 1]} assert_equal_data(result, expected) -def test_group_by_multiple_keys(constructor: Constructor) -> None: +def test_group_by_multiple_keys(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 4, 6], "c": [7, 2, 1]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() result = ( df.group_by("a", "b") .agg(c_min=nw.col("c").min(), c_max=nw.col("c").max()) @@ -289,13 +299,15 @@ def test_group_by_multiple_keys(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_key_with_nulls(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "modin" in str(constructor): +def test_key_with_nulls( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "modin" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail(reason="Modin flaky here", strict=False)) data = {"b": [4, 5, None], "a": [1, 2, 3]} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("b") .agg(nw.len(), nw.col("a").min()) .sort("a") @@ -305,10 +317,10 @@ def test_key_with_nulls(constructor: Constructor, request: pytest.FixtureRequest assert_equal_data(result, expected) -def test_key_with_nulls_ignored(constructor: Constructor) -> None: +def test_key_with_nulls_ignored(nw_frame_constructor: Constructor) -> None: data = {"b": [4, 5, None], "a": [1, 2, 3]} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("b", drop_null_keys=True) .agg(nw.len(), nw.col("a").min()) .sort("a") @@ -318,14 +330,14 @@ def test_key_with_nulls_ignored(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_key_with_nulls_iter(constructor_eager: ConstructorEager) -> None: +def test_key_with_nulls_iter(nw_eager_constructor: ConstructorEager) -> None: data = { "b": [None, "4", "5", None, "7"], "a": [None, 1, 2, 3, 4], "c": [None, "4", "3", None, None], } result = dict( - nw.from_native(constructor_eager(data), eager_only=True) + nw.from_native(nw_eager_constructor(data), eager_only=True) .group_by("b", "c", drop_null_keys=True) .__iter__() ) @@ -335,7 +347,7 @@ def test_key_with_nulls_iter(constructor_eager: ConstructorEager) -> None: assert_equal_data(result[("5", "3")], {"b": ["5"], "a": [2], "c": ["3"]}) result = dict( - nw.from_native(constructor_eager(data), eager_only=True) + nw.from_native(nw_eager_constructor(data), eager_only=True) .group_by("b", "c", drop_null_keys=False) .__iter__() ) @@ -344,17 +356,22 @@ def test_key_with_nulls_iter(constructor_eager: ConstructorEager) -> None: assert len(result) == 4 -def test_no_agg(constructor: Constructor) -> None: - result = nw.from_native(constructor(data)).group_by(["a", "b"]).agg().sort("a", "b") +def test_no_agg(nw_frame_constructor: Constructor) -> None: + result = ( + nw.from_native(nw_frame_constructor(data)) + .group_by(["a", "b"]) + .agg() + .sort("a", "b") + ) expected = {"a": [1, 3], "b": [4, 6]} assert_equal_data(result, expected) -def test_group_by_categorical(constructor: Constructor) -> None: - if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): +def test_group_by_categorical(nw_frame_constructor: Constructor) -> None: + if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): pytest.skip(reason="no categorical support") - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < ( 15, ): # pragma: no cover # https://github.com/narwhals-dev/narwhals/issues/1078 @@ -363,7 +380,7 @@ def test_group_by_categorical(constructor: Constructor) -> None: ) data = {"g1": ["a", "a", "b", "b"], "g2": ["x", "y", "x", "z"], "x": [1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.with_columns( g1=nw.col("g1").cast(nw.Categorical()), g2=nw.col("g2").cast(nw.Categorical()) @@ -375,40 +392,42 @@ def test_group_by_categorical(constructor: Constructor) -> None: assert_equal_data(result, data) -def test_group_by_shift_raises(constructor: Constructor) -> None: +def test_group_by_shift_raises(nw_frame_constructor: Constructor) -> None: df_native = {"a": [1, 2, 3], "b": [1, 1, 2]} - df = nw.from_native(constructor(df_native)) + df = nw.from_native(nw_frame_constructor(df_native)) with pytest.raises(InvalidOperationError, match="does not aggregate"): df.group_by("b").agg(nw.col("a").abs()) def test_double_same_aggregation( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("dask",)): + if any(x in str(nw_frame_constructor) for x in ("dask",)): # bugged in dask https://github.com/dask/dask/issues/11612 # and cudf https://github.com/rapidsai/cudf/issues/17649 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.group_by("a").agg(c=nw.col("b").mean(), d=nw.col("b").mean()).sort("a") expected = {"a": [1, 2], "c": [4.5, 6], "d": [4.5, 6]} assert_equal_data(result, expected) def test_all_kind_of_aggs( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("dask",)): + if any(x in str(nw_frame_constructor) for x in ("dask",)): # bugged in dask https://github.com/dask/dask/issues/11612 # and cudf https://github.com/rapidsai/cudf/issues/17649 request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor) and PANDAS_VERSION < (1, 4): + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 4): pytest.skip( "Pandas < 1.4.0 does not support multiple aggregations with the same column" ) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(constructor({"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]})) + df = nw.from_native( + nw_frame_constructor({"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]}) + ) result = ( df.group_by("a") .agg( @@ -454,8 +473,8 @@ def test_pandas_group_by_index_and_column_overlap() -> None: pd.testing.assert_frame_equal(result.to_native(), expected_native) -def test_fancy_functions(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) +def test_fancy_functions(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.group_by("a").agg(nw.all().std(ddof=0)).sort("a") expected = {"a": [1, 2], "b": [0.5, 0.0]} assert_equal_data(result, expected) @@ -518,14 +537,14 @@ def test_fancy_functions(constructor: Constructor) -> None: ], ) def test_group_by_expr( - constructor: Constructor, + nw_frame_constructor: Constructor, keys: list[nw.Expr], aggs: list[nw.Expr], expected: dict[str, list[Any]], sort_by: list[str], ) -> None: data = {"a": [1, 1, 2, 2, -1], "x": [0, 1, 2, 3, 4], "y": [0.5, -0.5, 1.0, -1.0, 1.5]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.group_by(*keys).agg(*aggs).sort(*sort_by) assert_equal_data(result, expected) @@ -541,19 +560,19 @@ def test_group_by_expr( ], ) def test_group_by_raise_if_not_preserves_length( - constructor: Constructor, keys: list[nw.Expr] + nw_frame_constructor: Constructor, keys: list[nw.Expr] ) -> None: data = {"a": [1, 2, 2, None], "b": [0, 1, 2, 3], "x": [1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.group_by(keys).agg(nw.col("x").max()) -def test_group_by_window(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_group_by_window(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 2, None], "b": [1, 1, 2, 2], "x": [1, 2, 3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = ( df.group_by(nw.col("a").mean().over("b")) .agg(nw.col("x").max()) @@ -567,17 +586,17 @@ def test_group_by_window(constructor: Constructor) -> None: "keys", [[nw.col("a").abs()], ["a", nw.col("a").abs().alias("a_test")]] ) def test_group_by_raise_drop_null_keys_with_exprs( - constructor: Constructor, keys: list[nw.Expr | str] + nw_frame_constructor: Constructor, keys: list[nw.Expr | str] ) -> None: data = {"a": [1, 1, 2, 2, -1], "x": [0, 1, 2, 3, 4], "y": [0.5, -0.5, 1.0, -1.0, 1.5]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises( NotImplementedError, match="drop_null_keys cannot be True when keys contains Expr" ): df.group_by(*keys, drop_null_keys=True) # type: ignore[call-overload] -def test_group_by_selector(constructor: Constructor) -> None: +def test_group_by_selector(nw_frame_constructor: Constructor) -> None: data = { "a": [1, 1, 1], "b": [4, 4, 6], @@ -585,7 +604,7 @@ def test_group_by_selector(constructor: Constructor) -> None: "x": [7.5, 8.5, 9.0], } result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by(nw.selectors.by_dtype(nw.Int64), "c") .agg(nw.col("x").mean()) .sort("a", "b") @@ -594,29 +613,33 @@ def test_group_by_selector(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_renaming_edge_case(constructor: Constructor) -> None: +def test_renaming_edge_case(nw_frame_constructor: Constructor) -> None: data = {"a": [0, 0, 0], "_a_tmp": [1, 2, 3], "b": [4, 5, 6]} - result = nw.from_native(constructor(data)).group_by(nw.col("a")).agg(nw.all().min()) + result = ( + nw.from_native(nw_frame_constructor(data)) + .group_by(nw.col("a")) + .agg(nw.all().min()) + ) expected = {"a": [0], "_a_tmp": [1], "b": [4]} assert_equal_data(result, expected) def test_group_by_len_1_column( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: """Based on a failure from marimo. - https://github.com/marimo-team/marimo/blob/036fd3ff89ef3a0e598bebb166637028024f98bc/tests/_plugins/ui/_impl/tables/test_narwhals.py#L1098-L1108 - https://github.com/marimo-team/marimo/blob/036fd3ff89ef3a0e598bebb166637028024f98bc/marimo/_plugins/ui/_impl/tables/narwhals_table.py#L163-L188 """ - if any(x in str(constructor) for x in ("dask",)): + if any(x in str(nw_frame_constructor) for x in ("dask",)): # `dask` # ValueError: conflicting aggregation functions: [('size', 'a'), ('size', 'a')] request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 1, 2, 3, 4]} expected = {"a": [1, 2, 3, 4], "len": [2, 2, 1, 1], "len_a": [2, 2, 1, 1]} result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .group_by("a") .agg(nw.len(), nw.len().alias("len_a")) .sort("a") @@ -651,7 +674,7 @@ def test_group_by_len_1_column( ) def test_group_by_no_preserve_dtype( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, low: NonNestedLiteral, high: NonNestedLiteral, ) -> None: @@ -663,7 +686,7 @@ def test_group_by_no_preserve_dtype( [aggregation that requires a function]: https://github.com/pandas-dev/pandas/issues/57317 """ if ( - "polars" in str(constructor_eager) + "polars" in str(nw_eager_constructor) and isinstance(low, Decimal) and POLARS_VERSION < (1, 21, 0) ): @@ -676,7 +699,7 @@ def test_group_by_no_preserve_dtype( "col_b": [low, low, high, high, None, None, None], } expected = {"col_a": [None, "A", "B"], "n_unique": [2, 3, 2]} - frame = nw.from_native(constructor_eager(data)) + frame = nw.from_native(nw_eager_constructor(data)) result = ( frame.group_by("col_a").agg(n_unique=nw.col("col_b").n_unique()).sort("col_a") ) @@ -685,10 +708,12 @@ def test_group_by_no_preserve_dtype( assert_equal_data(result, expected) -def test_top_level_len(constructor: Constructor) -> None: +def test_top_level_len(nw_frame_constructor: Constructor) -> None: # https://github.com/holoviz/holoviews/pull/6567#issuecomment-3178743331 df = nw.from_native( - constructor({"gender": ["m", "f", "f"], "weight": [4, 5, 6], "age": [None, 8, 9]}) + nw_frame_constructor( + {"gender": ["m", "f", "f"], "weight": [4, 5, 6], "age": [None, 8, 9]} + ) ) result = df.group_by(["gender"]).agg(nw.all().len()).sort("gender") expected = {"gender": ["f", "m"], "weight": [2, 1], "age": [2, 1]} @@ -717,7 +742,7 @@ def test_top_level_len(constructor: Constructor) -> None: ids=["no-sort", "sort-descending", "NA-order-nulls-first", "NA-order-nulls-last"], ) def test_group_by_agg_first( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, keys: Sequence[str], aggs: Sequence[str], expected: Mapping[str, Any], @@ -726,7 +751,7 @@ def test_group_by_agg_first( ) -> None: request.applymarker( pytest.mark.xfail( - "pyarrow_table" in str(constructor_eager) and (PYARROW_VERSION < (14, 0)), + "pyarrow_table" in str(nw_eager_constructor) and (PYARROW_VERSION < (14, 0)), reason="https://github.com/apache/arrow/issues/36709", raises=NotImplementedError, ) @@ -736,7 +761,7 @@ def test_group_by_agg_first( "b": [1, 2, 3, 4, 5, 6], "c": [None, "A", "A", None, "B", "B"], } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) if pre_sort: df = df.sort(aggs, **pre_sort) result = df.group_by(keys).agg(nw.col(aggs).first()).sort(keys) @@ -759,7 +784,7 @@ def test_group_by_agg_first( ids=["no-sort", "sort-descending", "NA-order-nulls-first", "NA-order-nulls-last"], ) def test_group_by_agg_last( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, keys: Sequence[str], aggs: Sequence[str], expected: Mapping[str, Any], @@ -768,7 +793,7 @@ def test_group_by_agg_last( ) -> None: request.applymarker( pytest.mark.xfail( - "pyarrow_table" in str(constructor_eager) and (PYARROW_VERSION < (14, 0)), + "pyarrow_table" in str(nw_eager_constructor) and (PYARROW_VERSION < (14, 0)), reason="https://github.com/apache/arrow/issues/36709", raises=NotImplementedError, ) @@ -778,19 +803,19 @@ def test_group_by_agg_last( "b": [1, 2, 3, 4, 5, 6], "c": [None, "A", "A", None, "B", "B"], } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) if pre_sort: df = df.sort(aggs, **pre_sort) result = df.group_by(keys).agg(nw.col(aggs).last()).sort(keys) assert_equal_data(result, expected) -def test_multi_column_expansion(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 32): +def test_multi_column_expansion(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/21773") - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="Internal error") - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = ( df.group_by("a") .agg(nw.all().sum().name.suffix("_aggregated")) diff --git a/tests/frame/head_test.py b/tests/frame/head_test.py index 1c9aaf4123..7c1124485a 100644 --- a/tests/frame/head_test.py +++ b/tests/frame/head_test.py @@ -4,11 +4,11 @@ from tests.utils import Constructor, assert_equal_data -def test_head(constructor: Constructor) -> None: +def test_head(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} expected = {"a": [1, 3], "b": [4, 4], "z": [7.0, 8.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.head(2) diff --git a/tests/frame/invalid_test.py b/tests/frame/invalid_test.py index d59b67adb1..6253406a56 100644 --- a/tests/frame/invalid_test.py +++ b/tests/frame/invalid_test.py @@ -14,9 +14,9 @@ @pytest.mark.skipif( POLARS_VERSION < (1,), reason="Polars would raise unrecoverable panic." ) -def test_all_vs_all(constructor: Constructor) -> None: +def test_all_vs_all(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises(MultiOutputExpressionError): df.lazy().select(nw.all() + nw.col("b", "a")).collect() diff --git a/tests/frame/is_duplicated_test.py b/tests/frame/is_duplicated_test.py index 0703d2bd6c..e644143525 100644 --- a/tests/frame/is_duplicated_test.py +++ b/tests/frame/is_duplicated_test.py @@ -4,18 +4,18 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_is_duplicated(constructor_eager: ConstructorEager) -> None: +def test_is_duplicated(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = nw.concat([df, df.head(1)]).is_duplicated() expected = {"is_duplicated": [True, False, False, True]} assert_equal_data({"is_duplicated": result}, expected) -def test_is_duplicated_with_nulls(constructor_eager: ConstructorEager) -> None: +def test_is_duplicated_with_nulls(nw_eager_constructor: ConstructorEager) -> None: data = {"col1": [1, 2, 3], "col2": ["one", None, None]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = df.is_duplicated() expected = {"is_duplicated": [False, False, False]} diff --git a/tests/frame/is_empty_test.py b/tests/frame/is_empty_test.py index 5464d0e678..55f193d8a3 100644 --- a/tests/frame/is_empty_test.py +++ b/tests/frame/is_empty_test.py @@ -12,10 +12,10 @@ @pytest.mark.parametrize(("threshold", "expected"), [(0, False), (10, True)]) def test_is_empty( - constructor_eager: ConstructorEager, threshold: Any, expected: Any + nw_eager_constructor: ConstructorEager, threshold: Any, expected: Any ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = df.filter(nw.col("a") > threshold).is_empty() assert result == expected diff --git a/tests/frame/is_unique_test.py b/tests/frame/is_unique_test.py index 10e9af910d..1309b40a4b 100644 --- a/tests/frame/is_unique_test.py +++ b/tests/frame/is_unique_test.py @@ -4,18 +4,18 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_is_unique(constructor_eager: ConstructorEager) -> None: +def test_is_unique(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = nw.concat([df, df.head(1)]).is_unique() expected = {"is_unique": [False, True, True, False]} assert_equal_data({"is_unique": result}, expected) -def test_is_unique_with_nulls(constructor_eager: ConstructorEager) -> None: +def test_is_unique_with_nulls(nw_eager_constructor: ConstructorEager) -> None: data = {"col1": [1, 2, 3, 3], "col2": ["one", None, None, None]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = df.is_unique() expected = {"is_unique": [True, True, False, False]} diff --git a/tests/frame/item_test.py b/tests/frame/item_test.py index 997b91d847..4f319090a6 100644 --- a/tests/frame/item_test.py +++ b/tests/frame/item_test.py @@ -11,13 +11,13 @@ @pytest.mark.parametrize(("row", "column", "expected"), [(0, 2, 7), (1, "z", 8)]) def test_item( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, row: int | None, column: int | str | None, expected: Any, ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert_equal_data({"a": [df.item(row, column)]}, {"a": [expected]}) assert_equal_data({"a": [df.select("a").head(1).item()]}, {"a": [1]}) @@ -35,11 +35,11 @@ def test_item( ], ) def test_item_value_error( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, row: int | None, column: int | str | None, err_msg: str, ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} with pytest.raises(ValueError, match=re.escape(err_msg)): - nw.from_native(constructor_eager(data), eager_only=True).item(row, column) + nw.from_native(nw_eager_constructor(data), eager_only=True).item(row, column) diff --git a/tests/frame/join_test.py b/tests/frame/join_test.py index e0228294e2..0322827277 100644 --- a/tests/frame/join_test.py +++ b/tests/frame/join_test.py @@ -105,10 +105,10 @@ def test_full_join( on: None | str | list[str], left_on: None | str | list[str], right_on: None | str | list[str], - constructor: Constructor, + nw_frame_constructor: Constructor, ) -> None: - df_left = from_native_lazy(constructor(df1)) - df_right = from_native_lazy(constructor(df2)) + df_left = from_native_lazy(nw_frame_constructor(df1)) + df_right = from_native_lazy(nw_frame_constructor(df2)) result = df_left.join( df_right, on=on, left_on=left_on, right_on=right_on, how="full" ).sort("id", nulls_last=True) @@ -116,22 +116,24 @@ def test_full_join( def test_full_join_duplicate( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: - if "ibis" in str(constructor): + if "ibis" in str(nw_frame_constructor): request.applymarker(pytest.mark.xfail) df1 = {"foo": [1, 2, 3], "val1": [1, 2, 3]} df2 = {"foo": [1, 2, 3], "foo_right": [1, 2, 3]} - df_left = from_native_lazy(constructor(df1)) - df_right = from_native_lazy(constructor(df2)) + df_left = from_native_lazy(nw_frame_constructor(df1)) + df_right = from_native_lazy(nw_frame_constructor(df2)) exceptions: list[type[Exception]] = [nw.exceptions.NarwhalsError] - if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): + if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( + nw_frame_constructor + ): from pyspark.errors import AnalysisException exceptions.append(AnalysisException) - elif "cudf" in str(constructor): + elif "cudf" in str(nw_frame_constructor): # cudf throw their own exception earlier in the stack exceptions.append(ValueError) @@ -139,14 +141,14 @@ def test_full_join_duplicate( df_left.join(df_right, on="foo", how="full").collect() -def test_inner_join_two_keys(constructor: Constructor) -> None: +def test_inner_join_two_keys(nw_frame_constructor: Constructor) -> None: data = { "antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0], "idx": [0, 1, 2], } - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) df_right = df result = df.join( df_right, @@ -168,14 +170,14 @@ def test_inner_join_two_keys(constructor: Constructor) -> None: assert_equal_data(result_on, expected) -def test_inner_join_single_key(constructor: Constructor) -> None: +def test_inner_join_single_key(nw_frame_constructor: Constructor) -> None: data = { "antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0], "idx": [0, 1, 2], } - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) df_right = df result = df.join( df_right, left_on="antananarivo", right_on="antananarivo", how="inner" @@ -195,11 +197,11 @@ def test_inner_join_single_key(constructor: Constructor) -> None: assert_equal_data(result_on, expected) -def test_cross_join(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4): +def test_cross_join(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4): pytest.skip() data = {"antananarivo": [1, 3, 2]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) result = df.join(df, how="cross").sort("antananarivo", "antananarivo_right") expected = { "antananarivo": [1, 1, 1, 2, 2, 2, 3, 3, 3], @@ -216,10 +218,10 @@ def test_cross_join(constructor: Constructor) -> None: @pytest.mark.parametrize("how", ["inner", "left"]) @pytest.mark.parametrize("suffix", ["_right", "_custom_suffix"]) def test_suffix( - constructor: Constructor, how: Literal["inner", "left"], suffix: str + nw_frame_constructor: Constructor, how: Literal["inner", "left"], suffix: str ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) df_right = df result = df.join( df_right, @@ -233,11 +235,11 @@ def test_suffix( @pytest.mark.parametrize("suffix", ["_right", "_custom_suffix"]) -def test_cross_join_suffix(constructor: Constructor, suffix: str) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4): +def test_cross_join_suffix(nw_frame_constructor: Constructor, suffix: str) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4): pytest.skip() data = {"antananarivo": [1, 3, 2]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) result = df.join(df, how="cross", suffix=suffix).sort( "antananarivo", f"antananarivo{suffix}" ) @@ -281,13 +283,13 @@ def test_cross_join_non_pandas() -> None: # pragma: no cover ], ) def test_anti_join( - constructor: Constructor, + nw_frame_constructor: Constructor, join_key: list[str], filter_expr: nw.Expr, expected: dict[str, list[Any]], ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) other = df.filter(filter_expr) result = df.join(other, how="anti", left_on=join_key, right_on=join_key) assert_equal_data(result, expected) @@ -319,13 +321,13 @@ def test_anti_join( ], ) def test_semi_join( - constructor: Constructor, + nw_frame_constructor: Constructor, join_key: list[str], filter_expr: nw.Expr, expected: dict[str, list[Any]], ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) other = df.filter(filter_expr) result = df.join(other, how="semi", left_on=join_key, right_on=join_key).sort( "antananarivo" @@ -334,9 +336,9 @@ def test_semi_join( @pytest.mark.parametrize("how", ["right"]) -def test_join_not_implemented(constructor: Constructor, how: str) -> None: +def test_join_not_implemented(nw_frame_constructor: Constructor, how: str) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) with pytest.raises( NotImplementedError, @@ -352,7 +354,7 @@ def test_join_not_implemented(constructor: Constructor, how: str) -> None: ) -def test_left_join(constructor: Constructor) -> None: +def test_left_join(nw_frame_constructor: Constructor) -> None: data_left = { "antananarivo": [1.0, 2.0, 3.0], "bob": [4.0, 5.0, 6.0], @@ -363,8 +365,8 @@ def test_left_join(constructor: Constructor) -> None: "co": [4.0, 5.0, 7.0], "idx": [0.0, 1.0, 2.0], } - df_left = from_native_lazy(constructor(data_left)) - df_right = from_native_lazy(constructor(data_right)) + df_left = from_native_lazy(nw_frame_constructor(data_left)) + df_right = from_native_lazy(nw_frame_constructor(data_right)) result = df_left.join(df_right, left_on="bob", right_on="co", how="left") result = result.sort("idx") result = result.drop("idx_right") @@ -386,11 +388,11 @@ def test_left_join(constructor: Constructor) -> None: assert_equal_data(result_on_list, expected_on_list) -def test_left_join_multiple_column(constructor: Constructor) -> None: +def test_left_join_multiple_column(nw_frame_constructor: Constructor) -> None: data_left = {"antananarivo": [1, 2, 3], "bob": [4, 5, 6], "idx": [0, 1, 2]} data_right = {"antananarivo": [1, 2, 3], "c": [4, 5, 6], "idx": [0, 1, 2]} - df_left = from_native_lazy(constructor(data_left)) - df_right = from_native_lazy(constructor(data_right)) + df_left = from_native_lazy(nw_frame_constructor(data_left)) + df_right = from_native_lazy(nw_frame_constructor(data_right)) result = df_left.join( df_right, left_on=["antananarivo", "bob"], @@ -403,7 +405,7 @@ def test_left_join_multiple_column(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_left_join_overlapping_column(constructor: Constructor) -> None: +def test_left_join_overlapping_column(nw_frame_constructor: Constructor) -> None: data_left = { "antananarivo": [1.0, 2.0, 3.0], "bob": [4.0, 5.0, 6.0], @@ -416,8 +418,8 @@ def test_left_join_overlapping_column(constructor: Constructor) -> None: "d": [1.0, 4.0, 2.0], "idx": [0.0, 1.0, 2.0], } - df_left = from_native_lazy(constructor(data_left)) - df_right = from_native_lazy(constructor(data_right)) + df_left = from_native_lazy(nw_frame_constructor(data_left)) + df_right = from_native_lazy(nw_frame_constructor(data_right)) result = df_left.join(df_right, left_on="bob", right_on="c", how="left").sort("idx") result = result.drop("idx_right") expected: dict[str, list[Any]] = { @@ -444,9 +446,11 @@ def test_left_join_overlapping_column(constructor: Constructor) -> None: @pytest.mark.parametrize("how", ["inner", "left", "semi", "anti"]) -def test_join_keys_exceptions(constructor: Constructor, how: JoinStrategy) -> None: +def test_join_keys_exceptions( + nw_frame_constructor: Constructor, how: JoinStrategy +) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) with pytest.raises( ValueError, @@ -497,30 +501,31 @@ def test_join_keys_exceptions(constructor: Constructor, how: JoinStrategy) -> No ], ) def test_joinasof_numeric( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, strategy: Literal["backward", "forward", "nearest"], expected: dict[str, list[Any]], ) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if ( - "duckdb" in str(constructor) or "ibis" in str(constructor) + "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor) ) and strategy == "nearest": request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) + ("pandas_pyarrow" in str(nw_frame_constructor)) + or ("pandas_nullable" in str(nw_frame_constructor)) ): request.applymarker(pytest.mark.xfail) data_left = {"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]} data_right = {"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]} - left_lf = from_native_lazy(constructor(data_left)).sort("antananarivo") - right_lf = from_native_lazy(constructor(data_right)).sort("antananarivo") + left_lf = from_native_lazy(nw_frame_constructor(data_left)).sort("antananarivo") + right_lf = from_native_lazy(nw_frame_constructor(data_right)).sort("antananarivo") result: nw.DataFrame[Any] | nw.LazyFrame[Any] result_on: nw.DataFrame[Any] | nw.LazyFrame[Any] - if constructor.is_lazy: + if nw_frame_constructor.is_lazy: result = left_lf.join_asof( right_lf, left_on="antananarivo", right_on="antananarivo", strategy=strategy ) @@ -579,21 +584,21 @@ def test_joinasof_numeric( ], ) def test_joinasof_time( - constructor: Constructor, + nw_frame_constructor: Constructor, request: pytest.FixtureRequest, strategy: Literal["backward", "forward", "nearest"], expected: dict[str, list[Any]], ) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if ( - "duckdb" in str(constructor) or "ibis" in str(constructor) + "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor) ) and strategy == "nearest": request.applymarker(pytest.mark.xfail) - if PANDAS_VERSION < (2, 1) and ("pandas_pyarrow" in str(constructor)): + if PANDAS_VERSION < (2, 1) and ("pandas_pyarrow" in str(nw_frame_constructor)): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - constructor( + nw_frame_constructor( { "datetime": [ datetime(2016, 3, 1), @@ -605,7 +610,7 @@ def test_joinasof_time( ) ).sort("datetime") df_right = from_native_lazy( - constructor( + nw_frame_constructor( { "datetime": [ datetime(2016, 1, 1), @@ -626,15 +631,18 @@ def test_joinasof_time( assert_equal_data(result_on.sort(by="datetime"), expected) -def test_joinasof_by(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): +def test_joinasof_by( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) + ("pandas_pyarrow" in str(nw_frame_constructor)) + or ("pandas_nullable" in str(nw_frame_constructor)) ): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - constructor( + nw_frame_constructor( { "antananarivo": [1, 5, 7, 10], "bob": ["D", "D", "C", "A"], @@ -643,7 +651,7 @@ def test_joinasof_by(constructor: Constructor, request: pytest.FixtureRequest) - ) ).sort("antananarivo") df_right = from_native_lazy( - constructor( + nw_frame_constructor( {"antananarivo": [1, 4, 5, 8], "bob": ["D", "D", "A", "F"], "d": [1, 3, 4, 1]} ) ).sort("antananarivo") @@ -660,19 +668,20 @@ def test_joinasof_by(constructor: Constructor, request: pytest.FixtureRequest) - def test_joinasof_suffix( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) + ("pandas_pyarrow" in str(nw_frame_constructor)) + or ("pandas_nullable" in str(nw_frame_constructor)) ): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - constructor({"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]}) + nw_frame_constructor({"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]}) ).sort("antananarivo") df_right = from_native_lazy( - constructor({"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]}) + nw_frame_constructor({"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]}) ).sort("antananarivo") result = df.join_asof( df_right, left_on="antananarivo", right_on="antananarivo", suffix="_y" @@ -683,10 +692,10 @@ def test_joinasof_suffix( @pytest.mark.parametrize("strategy", ["back", "furthest"]) def test_joinasof_not_implemented( - constructor: Constructor, strategy: Literal["backward", "forward"] + nw_frame_constructor: Constructor, strategy: Literal["backward", "forward"] ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) with pytest.raises( NotImplementedError, @@ -697,9 +706,9 @@ def test_joinasof_not_implemented( ) -def test_joinasof_keys_exceptions(constructor: Constructor) -> None: +def test_joinasof_keys_exceptions(nw_frame_constructor: Constructor) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) with pytest.raises( ValueError, @@ -757,7 +766,7 @@ def test_joinasof_keys_exceptions(constructor: Constructor) -> None: ], ) def test_joinasof_by_exceptions( - constructor: Constructor, + nw_frame_constructor: Constructor, on: str | None, by_left: str | list[str] | None, by_right: str | list[str] | None, @@ -765,9 +774,9 @@ def test_joinasof_by_exceptions( message: str, ) -> None: data = {ON: [1, 3, 2], BY: [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - frame = from_native_lazy(constructor(data)) + frame = from_native_lazy(nw_frame_constructor(data)) - if constructor.is_lazy: + if nw_frame_constructor.is_lazy: with pytest.raises(ValueError, match=message): frame.join_asof(frame, on=on, by_left=by_left, by_right=by_right, by=by) else: @@ -778,40 +787,42 @@ def test_joinasof_by_exceptions( def test_join_duplicate_column_names( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: exception: type[Exception] - if "polars" in str(constructor) and POLARS_VERSION < (1, 26): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 26): pytest.skip() if ( - "cudf" in str(constructor) + "cudf" in str(nw_frame_constructor) # TODO(unassigned): cudf doesn't raise here for some reason, # need to investigate. ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3, 4, 5], "b": [6, 6, 6, 6, 6]} - df = from_native_lazy(constructor(data)) + df = from_native_lazy(nw_frame_constructor(data)) if any( - x in str(constructor) + x in str(nw_frame_constructor) for x in ("pandas", "pandas[pyarrow]", "pandas[nullable]", "dask") ) and PANDAS_VERSION >= (3,): # pragma: no cover from pandas.errors import MergeError exception = MergeError - elif "pyspark" in str(constructor) and "sqlframe" not in str(constructor): + elif "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( + nw_frame_constructor + ): from pyspark.errors import AnalysisException exception = AnalysisException - elif "modin" in str(constructor): + elif "modin" in str(nw_frame_constructor): exception = NotImplementedError - elif "ibis" in str(constructor): + elif "ibis" in str(nw_frame_constructor): # ibis doesn't raise here request.applymarker(pytest.mark.xfail) else: exception = nw.exceptions.DuplicateError - if constructor.is_lazy: + if nw_frame_constructor.is_lazy: with pytest.raises(exception): df.join(df, on=["a"]).join(df, on=["a"]).collect() else: @@ -819,13 +830,13 @@ def test_join_duplicate_column_names( df.join(df, on=["a"]).join(df, on=["a"]) -def test_join_same_laziness(constructor: Constructor) -> None: +def test_join_same_laziness(nw_frame_constructor: Constructor) -> None: pytest.importorskip("polars") import polars as pl data_left = {"id": [1, 2, 3], "age": [25, 30, 35]} data_right = {"id": [2, 3, 4], "active": [False, True, True]} - frame = nw.from_native(constructor(data_left)) + frame = nw.from_native(nw_frame_constructor(data_left)) df_pl = pl.DataFrame(data_right) frame_pl: pl.DataFrame | pl.LazyFrame if isinstance(frame, nw.DataFrame): @@ -881,17 +892,17 @@ def test_join_same_laziness(constructor: Constructor) -> None: ], ) def test_join_on_null_values( - constructor: Constructor, how: JoinStrategy, expected: dict[str, list[Any]] + nw_frame_constructor: Constructor, how: JoinStrategy, expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4) and how=="cross": + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4) and how=="cross": pytest.skip() # See https://github.com/narwhals-dev/narwhals/issues/3307 keys = {"a": [1, 1, None, None], "b": [1, None, 5, None]} data_left = {**keys, "x": [1, 2, 3, 4]} data_right = {**keys, "y": [1.2, 3.4, 5.6, 7.8]} - df_left = from_native_lazy(constructor(data_left)) - df_right = from_native_lazy(constructor(data_right)) + df_left = from_native_lazy(nw_frame_constructor(data_left)) + df_right = from_native_lazy(nw_frame_constructor(data_right)) on = None if how == "cross" else list(keys) sort_by = ["a", "x", "y"] if how in {"cross", "full"} else ["a", "x"] @@ -904,7 +915,7 @@ def test_join_on_null_values( "ignore:.*Merging dataframes with merge column data type mismatches:UserWarning:dask" ) def test_full_join_with_overlapping_non_key_columns_and_nulls( - constructor: Constructor, + nw_frame_constructor: Constructor, ) -> None: data_left = { "id": [1, 2, 3], @@ -917,8 +928,8 @@ def test_full_join_with_overlapping_non_key_columns_and_nulls( "right_only": [100, 200, 300], } - df_left = from_native_lazy(constructor(data_left)) - df_right = from_native_lazy(constructor(data_right)) + df_left = from_native_lazy(nw_frame_constructor(data_left)) + df_right = from_native_lazy(nw_frame_constructor(data_right)) result = df_left.join(df_right, on="id", how="full", suffix="_r").sort( "id", nulls_last=True diff --git a/tests/frame/lazy_test.py b/tests/frame/lazy_test.py index 658a61c68b..5507513cfd 100644 --- a/tests/frame/lazy_test.py +++ b/tests/frame/lazy_test.py @@ -20,27 +20,27 @@ data = {"a": [1, 2, 3], "b": ["x", "y", "z"]} -def test_lazy_to_default(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_lazy_to_default(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.lazy() assert isinstance(result, nw.LazyFrame) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.lazy() assert isinstance(result, nw.LazyFrame) expected_cls: Any - if "polars" in str(constructor_eager): + if "polars" in str(nw_eager_constructor): import polars as pl expected_cls = pl.LazyFrame - elif "pandas" in str(constructor_eager): + elif "pandas" in str(nw_eager_constructor): import pandas as pd expected_cls = pd.DataFrame - elif "modin" in str(constructor_eager): + elif "modin" in str(nw_eager_constructor): mpd = get_modin() expected_cls = mpd.DataFrame - elif "cudf" in str(constructor_eager): + elif "cudf" in str(nw_eager_constructor): cudf = get_cudf() expected_cls = cudf.DataFrame else: # pyarrow @@ -70,21 +70,21 @@ def test_lazy_to_default(constructor_eager: ConstructorEager) -> None: ], ) def test_lazy( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, backend: LazyAllowed, request: pytest.FixtureRequest, ) -> None: impl = Implementation.from_backend(backend) pytest.importorskip(impl.name.lower()) if ( - "pandas_constructor" in str(constructor_eager) + "pandas_constructor" in str(nw_eager_constructor) and impl.is_duckdb() and PANDAS_VERSION >= (3,) and DUCKDB_VERSION < (1, 4, 4) ): # pragma: no cover # https://github.com/duckdb/duckdb/issues/18297 request.applymarker(pytest.mark.xfail) - if "pandas_nullable" in str(constructor_eager): + if "pandas_nullable" in str(nw_eager_constructor): pytest.importorskip("pyarrow") is_spark_connect = os.environ.get("SPARK_CONNECT", None) @@ -93,7 +93,7 @@ def test_lazy( # Implementation.PYSPARK_CONNECT, which is never installed. impl = Implementation.PYSPARK_CONNECT - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) session: Any if impl.is_sqlframe(): session = sqlframe_session() @@ -110,19 +110,19 @@ def test_lazy( @pytest.mark.parametrize("backend", ["pyspark", "sqlframe"]) def test_lazy_spark_like_requires_session( - constructor_eager: ConstructorEager, backend: SparkLike + nw_eager_constructor: ConstructorEager, backend: SparkLike ) -> None: impl = Implementation.from_backend(backend) pytest.importorskip(impl.name.lower()) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) err_msg = re.escape("Spark like backends require `session` to be not None.") with pytest.raises(ValueError, match=err_msg): df.lazy(backend=backend, session=None) -def test_lazy_backend_invalid(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) +def test_lazy_backend_invalid(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data), eager_only=True) with pytest.raises(ValueError, match="Not-supported backend"): df.lazy(backend=Implementation.PANDAS) # type: ignore[arg-type] diff --git a/tests/frame/len_test.py b/tests/frame/len_test.py index 3e709701c5..a63524c74a 100644 --- a/tests/frame/len_test.py +++ b/tests/frame/len_test.py @@ -9,7 +9,7 @@ data = {"a": [1.0, 2.0, None, 4.0], "b": [None, 3.0, None, 5.0]} -def test_len(constructor_eager: ConstructorEager) -> None: - result = len(nw.from_native(constructor_eager(data), eager_only=True)) +def test_len(nw_eager_constructor: ConstructorEager) -> None: + result = len(nw.from_native(nw_eager_constructor(data), eager_only=True)) assert result == 4 diff --git a/tests/frame/null_count_test.py b/tests/frame/null_count_test.py index eec6475c92..99fc071814 100644 --- a/tests/frame/null_count_test.py +++ b/tests/frame/null_count_test.py @@ -4,9 +4,9 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_null_count(constructor_eager: ConstructorEager) -> None: +def test_null_count(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [None, 3, 2], "b": [4, 4, 6], "z": [7.0, None, 9]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw, eager_only=True) result = df.null_count() expected = {"a": [1], "b": [0], "z": [1]} diff --git a/tests/frame/pipe_test.py b/tests/frame/pipe_test.py index 0a2eac992d..0e38ebe2d8 100644 --- a/tests/frame/pipe_test.py +++ b/tests/frame/pipe_test.py @@ -6,8 +6,8 @@ data = {"a": ["foo", "bars"], "ab": ["foo", "bars"]} -def test_pipe(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_pipe(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) columns = df.collect_schema().names() result = df.pipe(lambda _df: _df.select([x for x in columns if len(x) == 2])) expected = {"ab": ["foo", "bars"]} diff --git a/tests/frame/pivot_test.py b/tests/frame/pivot_test.py index 260006555e..67ace42095 100644 --- a/tests/frame/pivot_test.py +++ b/tests/frame/pivot_test.py @@ -113,20 +113,20 @@ ) @pytest.mark.parametrize(("on", "index"), [("col", "ix"), (["col"], ["ix"])]) def test_pivot( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, agg_func: str, expected: dict[str, list[Any]], on: str | list[str], index: str | list[str], request: pytest.FixtureRequest, ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.pivot( on=on, index=index, @@ -146,15 +146,15 @@ def test_pivot( ], ) def test_pivot_no_agg( - request: Any, constructor_eager: ConstructorEager, data_: Any, context: Any + request: Any, nw_eager_constructor: ConstructorEager, data_: Any, context: Any ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_), eager_only=True) with context: df.pivot("col", index="ix", aggregate_function=None) @@ -168,17 +168,17 @@ def test_pivot_no_agg( ) def test_pivot_sort_columns( request: Any, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, sort_columns: Any, expected: list[str], ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.pivot( on="col", index="ix", @@ -218,15 +218,15 @@ def test_pivot_sort_columns( ], ) def test_pivot_names_out( - request: Any, constructor_eager: ConstructorEager, kwargs: Any, expected: list[str] + request: Any, nw_eager_constructor: ConstructorEager, kwargs: Any, expected: list[str] ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = ( df.pivot(aggregate_function="min", index="ix", **kwargs).collect_schema().names() @@ -234,21 +234,21 @@ def test_pivot_names_out( assert result == expected -def test_pivot_no_index_no_values(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data_no_dups), eager_only=True) +def test_pivot_no_index_no_values(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data_no_dups), eager_only=True) with pytest.raises(ValueError, match="At least one of `values` and `index` must"): df.pivot(on="col") def test_pivot_no_index( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_no_dups), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_no_dups), eager_only=True) with pytest.warns(UserWarning, match="has no effect"): result = df.pivot(on="col", values="foo", maintain_order=True).sort("ix", "bar") expected = { diff --git a/tests/frame/rename_test.py b/tests/frame/rename_test.py index 11ec77185c..e0898d73b3 100644 --- a/tests/frame/rename_test.py +++ b/tests/frame/rename_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, assert_equal_data -def test_rename(constructor: Constructor) -> None: +def test_rename(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.rename({"a": "foo-bar", "b": "foo bar", "z": "z.b"}) expected = {"foo-bar": [1, 3, 2], "foo bar": [4, 4, 6], "z.b": [7.0, 8.0, 9.0]} assert_equal_data(result, expected) diff --git a/tests/frame/row_test.py b/tests/frame/row_test.py index 186fbf3478..e8ffbb54b7 100644 --- a/tests/frame/row_test.py +++ b/tests/frame/row_test.py @@ -10,10 +10,10 @@ from tests.utils import ConstructorEager -def test_row_column(request: Any, constructor_eager: ConstructorEager) -> None: - if "cudf" in str(constructor_eager): +def test_row_column(request: Any, nw_eager_constructor: ConstructorEager) -> None: + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0], "b": [11, 12, 13, 14, 15, 16]} - result = nw.from_native(constructor_eager(data), eager_only=True).row(2) + result = nw.from_native(nw_eager_constructor(data), eager_only=True).row(2) assert result == (3.0, 13) diff --git a/tests/frame/rows_test.py b/tests/frame/rows_test.py index 95fd2d8094..0a8851eed1 100644 --- a/tests/frame/rows_test.py +++ b/tests/frame/rows_test.py @@ -30,15 +30,15 @@ ) def test_iter_rows( request: Any, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = list(df.iter_rows(named=named)) assert result == expected @@ -61,11 +61,11 @@ def test_iter_rows( ], ) def test_rows( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.rows(named=named) assert result == expected @@ -88,24 +88,24 @@ def test_rows( ], ) def test_rows_eager( - constructor_eager: Any, + nw_eager_constructor: Any, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: # posit-dev/py-shiny relies on `.rows(named=False)` to return unnamed rows data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.rows(named=named) assert result == expected def test_rows_with_nulls_unnamed( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # cudf intentionally doesn't support itertuples / iter_rows request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_na), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) result = list(df.iter_rows(named=False)) expected = [(None, 4, 7.0), (3, 4, None), (2, 6, 9.0)] for i, row in enumerate(expected): @@ -120,12 +120,12 @@ def test_rows_with_nulls_unnamed( def test_rows_with_nulls_named( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # cudf intentionally doesn't support itertuples / iter_rows request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor_eager(data_na), eager_only=True) + df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) result = list(df.iter_rows(named=True)) expected: list[dict[str, Any]] = [ {"a": None, "b": 4, "z": 7.0}, diff --git a/tests/frame/sample_test.py b/tests/frame/sample_test.py index b86ddaee1d..46dbaa276f 100644 --- a/tests/frame/sample_test.py +++ b/tests/frame/sample_test.py @@ -8,9 +8,10 @@ from tests.utils import ConstructorEager -def test_sample_n(constructor_eager: ConstructorEager) -> None: +def test_sample_n(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), eager_only=True + nw_eager_constructor({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), + eager_only=True, ) result_expr = df.sample(n=2).shape @@ -18,9 +19,10 @@ def test_sample_n(constructor_eager: ConstructorEager) -> None: assert result_expr == expected_expr -def test_sample_fraction(constructor_eager: ConstructorEager) -> None: +def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: df = nw.from_native( - constructor_eager({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), eager_only=True + nw_eager_constructor({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), + eager_only=True, ) result_expr = df.sample(fraction=0.5).shape @@ -28,9 +30,9 @@ def test_sample_fraction(constructor_eager: ConstructorEager) -> None: assert result_expr == expected_expr -def test_sample_with_seed(constructor_eager: ConstructorEager) -> None: +def test_sample_with_seed(nw_eager_constructor: ConstructorEager) -> None: size, n = 100, 10 - df = nw.from_native(constructor_eager({"a": range(size)}), eager_only=True) + df = nw.from_native(nw_eager_constructor({"a": range(size)}), eager_only=True) r1 = nw.to_native(df.sample(n=n, seed=123)) r2 = nw.to_native(df.sample(n=n, seed=123)) diff --git a/tests/frame/schema_test.py b/tests/frame/schema_test.py index 93779cd129..95214f695b 100644 --- a/tests/frame/schema_test.py +++ b/tests/frame/schema_test.py @@ -32,9 +32,9 @@ @pytest.mark.filterwarnings("ignore:Determining|Resolving.*") -def test_schema(constructor: Constructor) -> None: +def test_schema(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) + nw_frame_constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) ) result = df.schema expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64} @@ -45,9 +45,9 @@ def test_schema(constructor: Constructor) -> None: assert result == expected -def test_collect_schema(constructor: Constructor) -> None: +def test_collect_schema(nw_frame_constructor: Constructor) -> None: df = nw.from_native( - constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) + nw_frame_constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) ) expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64} @@ -83,15 +83,15 @@ def test_string_disguised_as_object() -> None: def test_actual_object( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "cudf")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "cudf")): request.applymarker(pytest.mark.xfail) class Foo: ... data = {"a": [Foo()]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.schema assert result == {"a": nw.Object} @@ -569,7 +569,7 @@ def origin_arrow( @pytest.fixture def origin_pandas_like( - constructor_pandas_like: ConstructorPandasLike, + nw_pandas_like_constructor: ConstructorPandasLike, ) -> IntoPandasSchema: data: dict[str, Any] = { "a": [2, 1], @@ -578,18 +578,18 @@ def origin_pandas_like( "d": [5.3, 4.99], "e": [datetime(2006, 1, 1), datetime(2001, 9, 3)], } - return constructor_pandas_like(data).dtypes.to_dict() + return nw_pandas_like_constructor(data).dtypes.to_dict() @pytest.fixture def origin_pandas_like_pyarrow( - constructor_pandas_like: ConstructorPandasLike, + nw_pandas_like_constructor: ConstructorPandasLike, ) -> IntoPandasSchema: if PANDAS_VERSION < (1, 5): pytest.skip(reason="pandas too old for `pyarrow`") name_pandas_like = {"pandas_pyarrow_constructor", "modin_pyarrow_constructor"} - if str(constructor_pandas_like) not in name_pandas_like: - pytest.skip(f"{constructor_pandas_like!s} is not pandas_like_pyarrow") + if str(nw_pandas_like_constructor) not in name_pandas_like: + pytest.skip(f"{nw_pandas_like_constructor!s} is not pandas_like_pyarrow") data = { "a": [2, 1], "b": ["hello", "hi"], @@ -599,7 +599,7 @@ def origin_pandas_like_pyarrow( "f": [date(2003, 1, 1), date(2004, 1, 1)], "g": [time(10, 1, 1), time(14, 1, 1)], } - df_pd = constructor_pandas_like(data) + df_pd = nw_pandas_like_constructor(data) df_nw = nw.from_native(df_pd).with_columns( nw.col("f").cast(nw.Date()), nw.col("g").cast(nw.Time()) ) diff --git a/tests/frame/select_test.py b/tests/frame/select_test.py index ad8bce44f8..7acb1d5cb6 100644 --- a/tests/frame/select_test.py +++ b/tests/frame/select_test.py @@ -19,16 +19,18 @@ class Foo: ... -def test_select(constructor: Constructor) -> None: +def test_select(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select("a") expected = {"a": [1, 3, 2]} assert_equal_data(result, expected) -def test_empty_select(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True).select() +def test_empty_select(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native( + nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True + ).select() assert result.shape == (0, 0) @@ -52,9 +54,9 @@ def test_int_select_pandas() -> None: @pytest.mark.parametrize("invalid_select", [None, 0, Foo()]) -def test_invalid_select(constructor: Constructor, invalid_select: Any) -> None: +def test_invalid_select(nw_frame_constructor: Constructor, invalid_select: Any) -> None: with pytest.raises(InvalidIntoExprError): - nw.from_native(constructor({"a": [1, 2, 3]})).select(invalid_select) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})).select(invalid_select) def test_select_boolean_cols() -> None: @@ -99,7 +101,7 @@ def test_comparison_with_list_error_message() -> None: def test_missing_columns( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "ibis")): @@ -107,7 +109,7 @@ def test_missing_columns( request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) selected_columns = ["a", "e", "f"] if constructor_id == "polars[lazy]": @@ -140,12 +142,12 @@ def test_missing_columns( maybe_collect(df.select(nw.col("fdfa").sum())) -def test_left_to_right_broadcasting(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_left_to_right_broadcasting(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(constructor) and DASK_VERSION < (2024, 10): + if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): pytest.skip() - df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.select(nw.col("a") + nw.col("b").sum()) expected = {"a": [16, 16, 17]} assert_equal_data(result, expected) @@ -157,14 +159,14 @@ def test_left_to_right_broadcasting(constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_alias_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_alias_invalid(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises((NarwhalsError, ValueError)): df.lazy().select(nw.all().alias("c")).collect() -def test_filtration_vs_aggregation(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [1, None, 3]})) +def test_filtration_vs_aggregation(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, None, 3]})) result = df.select(nw.col("a").drop_nulls(), b=nw.col("a").mean()) expected: dict[str, Any] = {"a": [1, 3], "b": [2.0, 2.0]} assert_equal_data(result, expected) @@ -173,11 +175,11 @@ def test_filtration_vs_aggregation(constructor_eager: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_select_duplicates(constructor: Constructor) -> None: - if "cudf" in str(constructor): +def test_select_duplicates(nw_frame_constructor: Constructor) -> None: + if "cudf" in str(nw_frame_constructor): # cudf already raises its own error pytest.skip() - df = nw.from_native(constructor({"a": [1, 2]})).lazy() + df = nw.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() with pytest.raises( ValueError, match=r"Expected unique|[Dd]uplicate|more than one|Duplicate column name", @@ -185,8 +187,8 @@ def test_select_duplicates(constructor: Constructor) -> None: df.select("a", nw.col("a") + 1).collect() -def test_binary_window_aggregation(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [1, 1, 2]})) +def test_binary_window_aggregation(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, 1, 2]})) result = df.select(nw.col("a").cum_sum() + nw.col("a").sum()) expected = {"a": [5, 6, 8]} assert_equal_data(result, expected) diff --git a/tests/frame/shape_test.py b/tests/frame/shape_test.py index 4a4cf710b9..2637f20002 100644 --- a/tests/frame/shape_test.py +++ b/tests/frame/shape_test.py @@ -8,9 +8,9 @@ from tests.utils import ConstructorEager -def test_shape(constructor_eager: ConstructorEager) -> None: +def test_shape(nw_eager_constructor: ConstructorEager) -> None: result = nw.from_native( - constructor_eager({"a": [1, 2], "b": [4, 5], "c": [7, 8]}), eager_only=True + nw_eager_constructor({"a": [1, 2], "b": [4, 5], "c": [7, 8]}), eager_only=True ).shape expected = (2, 3) assert result == expected diff --git a/tests/frame/sink_parquet_test.py b/tests/frame/sink_parquet_test.py index 360828bded..29bc3f6d77 100644 --- a/tests/frame/sink_parquet_test.py +++ b/tests/frame/sink_parquet_test.py @@ -16,10 +16,12 @@ @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") -def test_sink_parquet(constructor: Constructor, tmpdir: pytest.TempdirFactory) -> None: - if "pandas" in str(constructor) and PANDAS_VERSION < (2, 0, 0): +def test_sink_parquet( + nw_frame_constructor: Constructor, tmpdir: pytest.TempdirFactory +) -> None: + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 0, 0): pytest.skip(reason="too old for pyarrow") path = tmpdir / "foo.parquet" # type: ignore[operator] - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) df.lazy().sink_parquet(str(path)) assert path.exists() diff --git a/tests/frame/sort_test.py b/tests/frame/sort_test.py index 4539d90606..97436703f1 100644 --- a/tests/frame/sort_test.py +++ b/tests/frame/sort_test.py @@ -6,9 +6,9 @@ from tests.utils import Constructor, assert_equal_data -def test_sort(constructor: Constructor) -> None: +def test_sort(nw_frame_constructor: Constructor) -> None: data = {"an tan": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.sort("an tan", "b") expected = {"an tan": [1, 2, 3], "b": [4, 6, 4], "z": [7.0, 9.0, 8.0]} assert_equal_data(result, expected) @@ -25,9 +25,9 @@ def test_sort(constructor: Constructor) -> None: ], ) def test_sort_nulls( - constructor: Constructor, *, nulls_last: bool, expected: dict[str, float] + nw_frame_constructor: Constructor, *, nulls_last: bool, expected: dict[str, float] ) -> None: data = {"antan desc": [0, 0, 2, -1], "b": [1, 3, 2, None]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.sort("b", descending=True, nulls_last=nulls_last) assert_equal_data(result, expected) diff --git a/tests/frame/tail_test.py b/tests/frame/tail_test.py index 4fdf4da8ef..034ffd0783 100644 --- a/tests/frame/tail_test.py +++ b/tests/frame/tail_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_tail(constructor_eager: ConstructorEager) -> None: +def test_tail(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw) result = df.tail(2) assert_equal_data(result, expected) diff --git a/tests/frame/to_arrow_test.py b/tests/frame/to_arrow_test.py index 3bb74a9dc7..3a7b147556 100644 --- a/tests/frame/to_arrow_test.py +++ b/tests/frame/to_arrow_test.py @@ -14,9 +14,9 @@ @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") -def test_to_arrow(constructor_eager: ConstructorEager) -> None: +def test_to_arrow(nw_eager_constructor: ConstructorEager) -> None: data: dict[str, Any] = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) result = nw.from_native(df_raw, eager_only=True).to_arrow() expected = pa.table(data) diff --git a/tests/frame/to_dict_test.py b/tests/frame/to_dict_test.py index c382a0619f..0feb2e4938 100644 --- a/tests/frame/to_dict_test.py +++ b/tests/frame/to_dict_test.py @@ -9,16 +9,16 @@ @pytest.mark.filterwarnings( "ignore:.*all arguments of to_dict except for the argument:FutureWarning" ) -def test_to_dict(constructor_eager: ConstructorEager) -> None: +def test_to_dict(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.to_dict(as_series=False) assert result == data -def test_to_dict_as_series(constructor_eager: ConstructorEager) -> None: +def test_to_dict_as_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = df.to_dict(as_series=True) assert isinstance(result["a"], nw.Series) assert isinstance(result["b"], nw.Series) diff --git a/tests/frame/to_native_test.py b/tests/frame/to_native_test.py index 0ef0ae885a..f96cd5d8bd 100644 --- a/tests/frame/to_native_test.py +++ b/tests/frame/to_native_test.py @@ -8,9 +8,9 @@ from tests.utils import Constructor -def test_to_native(constructor: Constructor) -> None: +def test_to_native(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) assert isinstance(df.to_native(), df_raw.__class__) diff --git a/tests/frame/to_numpy_test.py b/tests/frame/to_numpy_test.py index 9330a2c7b3..70c426c70b 100644 --- a/tests/frame/to_numpy_test.py +++ b/tests/frame/to_numpy_test.py @@ -15,9 +15,9 @@ from tests.utils import ConstructorEager -def test_to_numpy(constructor_eager: ConstructorEager) -> None: +def test_to_numpy(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) result = nw.from_native(df_raw, eager_only=True).to_numpy() expected = np.array([[1, 3, 2], [4, 4, 6], [7.1, 8.0, 9.0]]).T np.testing.assert_array_equal(result, expected) @@ -25,14 +25,14 @@ def test_to_numpy(constructor_eager: ConstructorEager) -> None: def test_to_numpy_tz_aware( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) or ( - "pyarrow" in str(constructor_eager) and is_windows() + if ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) or ( + "pyarrow" in str(nw_eager_constructor) and is_windows() ): request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor_eager({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), + nw_eager_constructor({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), eager_only=True, ) df = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) diff --git a/tests/frame/to_pandas_test.py b/tests/frame/to_pandas_test.py index b74c9a98b1..ca9ec2d673 100644 --- a/tests/frame/to_pandas_test.py +++ b/tests/frame/to_pandas_test.py @@ -16,15 +16,15 @@ @pytest.mark.filterwarnings("ignore:.*Passing a BlockManager.*:DeprecationWarning") @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pandas-pyarrow") -def test_convert_pandas(constructor_eager: ConstructorEager) -> None: +def test_convert_pandas(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("pyarrow") data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) result = nw.from_native(df_raw, eager_only=True).to_pandas() - if str(constructor_eager).startswith("pandas"): - expected = cast("pd.DataFrame", constructor_eager(data)) - elif "modin_pyarrow" in str(constructor_eager): + if str(nw_eager_constructor).startswith("pandas"): + expected = cast("pd.DataFrame", nw_eager_constructor(data)) + elif "modin_pyarrow" in str(nw_eager_constructor): expected = pd.DataFrame(data).convert_dtypes(dtype_backend="pyarrow") else: expected = pd.DataFrame(data) diff --git a/tests/frame/to_polars_test.py b/tests/frame/to_polars_test.py index 89d4a65b2a..d0faf59240 100644 --- a/tests/frame/to_polars_test.py +++ b/tests/frame/to_polars_test.py @@ -15,12 +15,12 @@ @pytest.mark.filterwarnings("ignore:.*Passing a BlockManager.*:DeprecationWarning") -def test_convert_polars(constructor_eager: ConstructorEager) -> None: +def test_convert_polars(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("pyarrow") from polars.testing import assert_frame_equal data: Data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) result = nw.from_native(df_raw).to_polars() expected = pl.DataFrame(data) diff --git a/tests/frame/top_k_test.py b/tests/frame/top_k_test.py index d0ba228df0..6de02d7bfb 100644 --- a/tests/frame/top_k_test.py +++ b/tests/frame/top_k_test.py @@ -6,35 +6,35 @@ from tests.utils import DUCKDB_VERSION, POLARS_VERSION, Constructor, assert_equal_data -def test_top_k(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 0): +def test_top_k(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0): # old polars versions do not sort nulls last pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": ["a", "f", "a", "d", "b", "c"], "b c": [None, None, 2, 3, 6, 1]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.top_k(4, by="b c") expected = {"a": ["a", "b", "c", "d"], "b c": [2, 6, 1, 3]} assert_equal_data(result.sort("a"), expected) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.top_k(4, by="b c", reverse=True) expected = {"a": ["a", "b", "c", "d"], "b c": [2, 6, 1, 3]} assert_equal_data(result.sort(by="a"), expected) -def test_top_k_by_multiple(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 22): +def test_top_k_by_multiple(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 22): # bug in old version pytest.skip() - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { "a": ["a", "f", "a", "d", "b", "c"], "b": [2, 2, 2, 3, 1, 1], "sf_c": ["k", "d", "s", "a", "a", "r"], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.top_k(4, by=["b", "sf_c"], reverse=True) expected = { "a": ["b", "f", "a", "c"], @@ -47,7 +47,7 @@ def test_top_k_by_multiple(constructor: Constructor) -> None: "b": [2, 2, 2, 3, 1, 1], "sf_c": ["k", "d", "s", "a", "a", "r"], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.top_k(4, by=["b", "sf_c"], reverse=[False, True]) expected = { "a": ["d", "f", "a", "a"], diff --git a/tests/frame/unique_test.py b/tests/frame/unique_test.py index 691540d0a2..26a22cebd2 100644 --- a/tests/frame/unique_test.py +++ b/tests/frame/unique_test.py @@ -20,12 +20,12 @@ ], ) def test_unique_eager( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, subset: str | list[str] | None, keep: Literal["first", "last"], expected: dict[str, list[float]], ) -> None: - df_raw = constructor_eager(data) + df_raw = nw_eager_constructor(data) df = nw.from_native(df_raw) result = df.unique(subset, keep=keep).sort("z") assert_equal_data(result, expected) @@ -39,18 +39,18 @@ def test_unique_eager( ], ) def test_unique_first_last( - constructor: Constructor, + nw_frame_constructor: Constructor, keep: Literal["first", "last"], expected: dict[str, list[float]], request: pytest.FixtureRequest, ) -> None: - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/12073 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"i": [0, 1, None, 2], "a": [1, 3, 2, 1], "b": [4, 4, 4, 6]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.unique("b", keep=keep, order_by="i").sort("i") assert_equal_data(result, expected) @@ -68,14 +68,14 @@ def test_unique_first_last( ], ) def test_unique_first_last_no_subset( - constructor: Constructor, + nw_frame_constructor: Constructor, keep: Literal["first", "last"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"i": [0, 1, 1, 2], "b": [4, 4, 4, 6]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.unique(keep=keep, order_by="i").sort("i") assert_equal_data(result, expected) @@ -85,10 +85,10 @@ def test_unique_first_last_no_subset( assert_equal_data(result, expected) -def test_unique_invalid(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_invalid(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) with pytest.raises(ColumnNotFoundError): df.lazy().unique(["fdssfad"]).collect() @@ -104,13 +104,13 @@ def test_unique_invalid(constructor: Constructor) -> None: ], ) def test_unique( - constructor: Constructor, + nw_frame_constructor: Constructor, keep: Literal["any", "none"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.unique(["b"], keep=keep).sort("z") assert_equal_data(result, expected) @@ -122,30 +122,30 @@ def test_unique( [("any", {"a": [1, 1, 2], "b": [3, 4, 4]}), ("none", {"a": [1, 2], "b": [4, 4]})], ) def test_unique_full_subset( - constructor: Constructor, + nw_frame_constructor: Constructor, subset: list[str] | None, keep: Literal["any", "none"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 1, 2], "b": [3, 3, 4, 4]} - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.unique(subset, keep=keep).sort("a", "b") assert_equal_data(result, expected) -def test_unique_invalid_keep(constructor: Constructor) -> None: +def test_unique_invalid_keep(nw_frame_constructor: Constructor) -> None: with pytest.raises(ValueError, match=r"(Got|got): cabbage"): - nw.from_native(constructor(data)).unique(keep="cabbage") # type: ignore[arg-type] + nw.from_native(nw_frame_constructor(data)).unique(keep="cabbage") # type: ignore[arg-type] @pytest.mark.filterwarnings("ignore:.*backwards-compatibility:UserWarning") -def test_unique_none(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_none(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = constructor(data) + df_raw = nw_frame_constructor(data) df = nw.from_native(df_raw) result = df.unique().sort("z") @@ -156,11 +156,11 @@ def test_unique_none(constructor: Constructor) -> None: assert_equal_data(result, data) -def test_unique_3069(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_3069(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"name": ["a", "b", "c"], "group": ["d", "e", "f"], "value": [1, 2, 3]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) unique_to_get = "group" result = df.select(nw.col(unique_to_get)).unique().sort(unique_to_get) expected = {"group": ["d", "e", "f"]} diff --git a/tests/frame/unpivot_test.py b/tests/frame/unpivot_test.py index 8d661ae1de..66e2283382 100644 --- a/tests/frame/unpivot_test.py +++ b/tests/frame/unpivot_test.py @@ -49,12 +49,12 @@ ], ) def test_unpivot( - constructor: Constructor, + nw_frame_constructor: Constructor, on: str | list[str] | None, index: list[str] | None, expected: dict[str, list[float]], ) -> None: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) sort_columns = ["variable"] if index is None else ["variable", "a"] result = df.unpivot(on=on, index=index).sort(by=sort_columns) assert_equal_data(result, expected) @@ -69,24 +69,24 @@ def test_unpivot( ], ) def test_unpivot_var_value_names( - constructor: Constructor, variable_name: str, value_name: str + nw_frame_constructor: Constructor, variable_name: str, value_name: str ) -> None: context = ( pytest.raises(NotImplementedError) if ( any([variable_name == "", value_name == ""]) and ( - "duckdb" in str(constructor) + "duckdb" in str(nw_frame_constructor) # This might depend from the dialect we use in sqlframe. # Since for now we use only duckdb, we need to xfail it - or "sqlframe" in str(constructor) + or "sqlframe" in str(nw_frame_constructor) ) ) else does_not_raise() ) with context: - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.unpivot( on=["b", "c"], index=["a"], variable_name=variable_name, value_name=value_name ) @@ -94,8 +94,8 @@ def test_unpivot_var_value_names( assert result.collect_schema().names()[-2:] == [variable_name, value_name] -def test_unpivot_default_var_value_names(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_unpivot_default_var_value_names(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.unpivot(on=["b", "c"], index=["a"]) assert result.collect_schema().names()[-2:] == ["variable", "value"] @@ -112,16 +112,16 @@ def test_unpivot_default_var_value_names(constructor: Constructor) -> None: ) def test_unpivot_mixed_types( request: pytest.FixtureRequest, - constructor: Constructor, + nw_frame_constructor: Constructor, data: dict[str, Any], expected_dtypes: list[DType], ) -> None: - if "cudf" in str(constructor) or ( - "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0, 0) + if "cudf" in str(nw_frame_constructor) or ( + "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0, 0) ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.unpivot(on=["a", "b"], index="idx") assert result.collect_schema().dtypes() == expected_dtypes diff --git a/tests/frame/with_columns_sequence_test.py b/tests/frame/with_columns_sequence_test.py index 106f473886..a74adcffc2 100644 --- a/tests/frame/with_columns_sequence_test.py +++ b/tests/frame/with_columns_sequence_test.py @@ -11,9 +11,9 @@ data = {"a": ["foo", "bars"], "ab": ["foo", "bars"]} -def test_with_columns(constructor_eager: ConstructorEager) -> None: +def test_with_columns(nw_eager_constructor: ConstructorEager) -> None: result = ( - nw.from_native(constructor_eager(data)) + nw.from_native(nw_eager_constructor(data)) .with_columns(d=np.array([4, 5])) # pyright: ignore[reportArgumentType] .with_columns(e=nw.col("d") + 1) .select("d", "e") diff --git a/tests/frame/with_columns_test.py b/tests/frame/with_columns_test.py index e2325e9347..36de016c25 100644 --- a/tests/frame/with_columns_test.py +++ b/tests/frame/with_columns_test.py @@ -28,34 +28,34 @@ def test_with_columns_int_col_name_pandas() -> None: pd.testing.assert_frame_equal(result, expected) -def test_with_columns_order(constructor: Constructor) -> None: +def test_with_columns_order(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1) assert result.collect_schema().names() == ["a", "b", "z", "d"] expected = {"a": [2, 4, 3], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "d": [0, 2, 1]} assert_equal_data(result, expected) -def test_with_columns_empty(constructor_eager: ConstructorEager) -> None: +def test_with_columns_empty(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df.select().with_columns() assert_equal_data(result, {}) -def test_select_with_columns_empty_lazy(constructor: Constructor) -> None: +def test_select_with_columns_empty_lazy(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(constructor(data)).lazy() + df = nw.from_native(nw_frame_constructor(data)).lazy() with pytest.raises(ValueError, match="At least one"): df.with_columns() with pytest.raises(ValueError, match="At least one"): df.select() -def test_with_columns_order_single_row(constructor: Constructor) -> None: +def test_with_columns_order_single_row(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "i": [0, 1, 2]} - df = nw.from_native(constructor(data)).filter(nw.col("i") < 1).drop("i") + df = nw.from_native(nw_frame_constructor(data)).filter(nw.col("i") < 1).drop("i") result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1) assert result.collect_schema().names() == ["a", "b", "z", "d"] expected = {"a": [2], "b": [4], "z": [7.0], "d": [0]} @@ -63,42 +63,46 @@ def test_with_columns_order_single_row(constructor: Constructor) -> None: def test_with_columns_dtypes_single_row( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (15,): + if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (15,): pytest.skip() if ( - ("pyspark" in str(constructor)) - or "duckdb" in str(constructor) - or "ibis" in str(constructor) + ("pyspark" in str(nw_frame_constructor)) + or "duckdb" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) data = {"a": ["foo"]} - df = nw.from_native(constructor(data)).with_columns(nw.col("a").cast(nw.Categorical)) + df = nw.from_native(nw_frame_constructor(data)).with_columns( + nw.col("a").cast(nw.Categorical) + ) result = df.with_columns(nw.col("a")) assert result.collect_schema() == {"a": nw.Categorical} -def test_with_columns_series_shape_mismatch(constructor_eager: ConstructorEager) -> None: - df1 = nw.from_native(constructor_eager({"first": [1, 2, 3]}), eager_only=True) - second = nw.from_native(constructor_eager({"second": [1, 2, 3, 4]}), eager_only=True)[ - "second" - ] +def test_with_columns_series_shape_mismatch( + nw_eager_constructor: ConstructorEager, +) -> None: + df1 = nw.from_native(nw_eager_constructor({"first": [1, 2, 3]}), eager_only=True) + second = nw.from_native( + nw_eager_constructor({"second": [1, 2, 3, 4]}), eager_only=True + )["second"] with pytest.raises(ShapeError): df1.with_columns(second=second) def test_with_columns_missing_column( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "ibis")): # `sqlframe` raises a different error depending on its underlying backend request.applymarker(pytest.mark.xfail) data = {"a": [1, 2], "b": [3, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) - if "polars" in str(constructor): + if "polars" in str(nw_frame_constructor): msg = r"c" elif any(id_ == constructor_id for id_ in ("duckdb", "pyspark")): msg = r"\n\nHint: Did you mean one of these columns: \['a', 'b'\]?" diff --git a/tests/frame/with_row_index_test.py b/tests/frame/with_row_index_test.py index 10310ca7f6..32251a024d 100644 --- a/tests/frame/with_row_index_test.py +++ b/tests/frame/with_row_index_test.py @@ -20,8 +20,8 @@ data = {"abc": ["foo", "bars"], "xyz": [100, 200], "const": [42, 42]} -def test_with_row_index_eager(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager(data), eager_only=True).with_row_index() +def test_with_row_index_eager(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native(nw_eager_constructor(data), eager_only=True).with_row_index() expected = {"index": [0, 1], **data} assert_equal_data(result, expected) @@ -36,20 +36,24 @@ def test_with_row_index_eager(constructor_eager: ConstructorEager) -> None: ], ) def test_with_row_index_lazy( - constructor: Constructor, order_by: str | Sequence[str], expected_index: list[int] + nw_frame_constructor: Constructor, + order_by: str | Sequence[str], + expected_index: list[int], ) -> None: if ( - "pandas" in str(constructor) and PANDAS_VERSION < (1, 3) and order_by == "abc" + "pandas" in str(nw_frame_constructor) + and PANDAS_VERSION < (1, 3) + and order_by == "abc" ): # pragma: no cover reason = "ValueError: first not supported for non-numeric data." pytest.skip(reason=reason) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() result = ( - nw.from_native(constructor(data)) + nw.from_native(nw_frame_constructor(data)) .with_row_index(name="foo bar", order_by=order_by) .sort("xyz") ) @@ -57,8 +61,8 @@ def test_with_row_index_lazy( assert_equal_data(result, expected) -def test_with_row_index_lazy_exception(constructor: Constructor) -> None: - frame = nw.from_native(constructor(data)) +def test_with_row_index_lazy_exception(nw_frame_constructor: Constructor) -> None: + frame = nw.from_native(nw_frame_constructor(data)) msg = r"(LazyFrame\.)?with_row_index\(\) missing 1 required keyword-only argument: 'order_by'$" if isinstance(frame, nw.LazyFrame): with pytest.raises(TypeError, match=msg): @@ -78,18 +82,21 @@ def test_with_row_index_lazy_exception(constructor: Constructor) -> None: ], ) def test_with_row_index_lazy_meaner_examples( - constructor: Constructor, order_by: list[str], expected_index: list[int] + nw_frame_constructor: Constructor, order_by: list[str], expected_index: list[int] ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3289 - if "polars" in str(constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "pandas" in str(constructor) and PANDAS_VERSION < (1, 3): # pragma: no cover + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < ( + 1, + 3, + ): # pragma: no cover reason = "ValueError: first not supported for non-numeric data." pytest.skip(reason=reason) - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": ["A", "B", "A"], "b": [1, 2, 3], "c": [9, 2, 4]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.with_row_index(name="index", order_by=order_by).sort("b") expected = {"index": expected_index, **data} assert_equal_data(result, expected) diff --git a/tests/frame/write_csv_test.py b/tests/frame/write_csv_test.py index 5f907ac78c..945051cb47 100644 --- a/tests/frame/write_csv_test.py +++ b/tests/frame/write_csv_test.py @@ -10,17 +10,19 @@ def test_write_csv( - constructor_eager: ConstructorEager, tmpdir: pytest.TempdirFactory + nw_eager_constructor: ConstructorEager, tmpdir: pytest.TempdirFactory ) -> None: data = {"a": [1, 2, 3]} path = tmpdir / "foo.csv" # type: ignore[operator] - result = nw.from_native(constructor_eager(data), eager_only=True).write_csv(str(path)) + result = nw.from_native(nw_eager_constructor(data), eager_only=True).write_csv( + str(path) + ) assert path.exists() assert result is None - result = nw.from_native(constructor_eager(data), eager_only=True).write_csv() + result = nw.from_native(nw_eager_constructor(data), eager_only=True).write_csv() if is_windows(): # pragma: no cover result = result.replace("\r\n", "\n") - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): assert result == '"a"\n1\n2\n3\n' else: assert result == "a\n1\n2\n3\n" diff --git a/tests/frame/write_parquet_test.py b/tests/frame/write_parquet_test.py index cf86f1be00..69443245b3 100644 --- a/tests/frame/write_parquet_test.py +++ b/tests/frame/write_parquet_test.py @@ -17,8 +17,8 @@ @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pyarrow") @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") def test_write_parquet( - constructor_eager: ConstructorEager, tmpdir: pytest.TempdirFactory + nw_eager_constructor: ConstructorEager, tmpdir: pytest.TempdirFactory ) -> None: path = tmpdir / "foo.parquet" # type: ignore[operator] - nw.from_native(constructor_eager(data), eager_only=True).write_parquet(str(path)) + nw.from_native(nw_eager_constructor(data), eager_only=True).write_parquet(str(path)) assert path.exists() diff --git a/tests/from_dict_test.py b/tests/from_dict_test.py index 93ea5b2880..c89b4a0fc6 100644 --- a/tests/from_dict_test.py +++ b/tests/from_dict_test.py @@ -36,12 +36,14 @@ def test_from_dict_schema(eager_backend: EagerAllowed) -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) -def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> None: +def test_from_dict_without_backend( + nw_frame_constructor: Constructor, backend: Polars +) -> None: pytest.importorskip("polars") pytest.importorskip("pyarrow") df = ( - nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) @@ -49,8 +51,12 @@ def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> assert_equal_data(result, {"c": [1, 2, 3], "d": [4, 5, 6]}) -def test_from_dict_without_backend_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).lazy().collect() +def test_from_dict_without_backend_invalid(nw_frame_constructor: Constructor) -> None: + df = ( + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + .lazy() + .collect() + ) with pytest.raises(TypeError, match="backend"): nw.from_dict({"c": nw.to_native(df["a"]), "d": nw.to_native(df["b"])}) @@ -63,13 +69,13 @@ def test_from_dict_with_backend_invalid() -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) def test_from_dict_one_native_one_narwhals( - constructor: Constructor, backend: Polars + nw_frame_constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") df = ( - nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) diff --git a/tests/from_numpy_test.py b/tests/from_numpy_test.py index e8ebcbc6f0..b66ee738a6 100644 --- a/tests/from_numpy_test.py +++ b/tests/from_numpy_test.py @@ -23,32 +23,32 @@ } -def test_from_numpy(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_from_numpy(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend) assert_equal_data(result, expected) assert isinstance(result, nw.DataFrame) -def test_from_numpy_schema_dict(constructor_eager: ConstructorEager) -> None: +def test_from_numpy_schema_dict(nw_eager_constructor: ConstructorEager) -> None: schema = {"c": nw.Int16(), "d": nw.Float32(), "e": nw.Int16(), "f": nw.Float64()} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend, schema=schema) assert result.collect_schema() == schema -def test_from_numpy_schema_list(constructor_eager: ConstructorEager) -> None: +def test_from_numpy_schema_list(nw_eager_constructor: ConstructorEager) -> None: schema = ["c", "d", "e", "f"] - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend, schema=schema) assert result.columns == schema -def test_from_numpy_schema_notvalid(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_from_numpy_schema_notvalid(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) backend = nw.get_native_namespace(df) with pytest.raises(TypeError, match=r"`schema.*expected.*types"): nw.from_numpy(arr, schema=5, backend=backend) # type: ignore[arg-type] @@ -60,8 +60,8 @@ def test_from_numpy_non_eager() -> None: nw.from_numpy(arr, backend="duckdb") # type: ignore[arg-type] -def test_from_numpy_not2d(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager(data)) +def test_from_numpy_not2d(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor(data)) backend = nw.get_native_namespace(df) with pytest.raises(ValueError, match="`from_numpy` only accepts 2D numpy arrays"): nw.from_numpy(np.array([0]), backend=backend) # pyright: ignore[reportArgumentType] diff --git a/tests/joblib_test.py b/tests/joblib_test.py index 72b9440544..23060aa66c 100644 --- a/tests/joblib_test.py +++ b/tests/joblib_test.py @@ -12,12 +12,12 @@ from joblib import Parallel, delayed -def test_parallelisability(constructor_eager: ConstructorEager) -> None: +def test_parallelisability(nw_eager_constructor: ConstructorEager) -> None: # https://github.com/narwhals-dev/narwhals/issues/2450 def do_something(df: nw.DataFrame[Any]) -> nw.DataFrame[Any]: # pragma: no cover return df.with_columns(nw.col("col1") * 2) - dfs = [nw.from_native(constructor_eager({"col1": [0, 2], "col2": [3, 7]}))] + dfs = [nw.from_native(nw_eager_constructor({"col1": [0, 2], "col2": [3, 7]}))] result = list(Parallel(n_jobs=-1)(delayed(do_something)(df_) for df_ in dfs)) assert len(result) == 1 expected = {"col1": [0, 4], "col2": [3, 7]} @@ -25,10 +25,10 @@ def do_something(df: nw.DataFrame[Any]) -> nw.DataFrame[Any]: # pragma: no cove def test_parallelisability_series( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: # https://github.com/narwhals-dev/narwhals/issues/2450 - if "modin" in str(constructor_eager): + if "modin" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) def do_something(s: nw.Series[Any]) -> nw.Series[Any]: # pragma: no cover @@ -36,7 +36,7 @@ def do_something(s: nw.Series[Any]) -> nw.Series[Any]: # pragma: no cover columns = [ nw.from_native( - constructor_eager({"col1": [0, 2], "col2": [3, 7]}), eager_only=True + nw_eager_constructor({"col1": [0, 2], "col2": [3, 7]}), eager_only=True )["col1"] ] result = list( diff --git a/tests/modern_polars/ewm_mean_test.py b/tests/modern_polars/ewm_mean_test.py index 0b3ea06923..2d2ebcadd2 100644 --- a/tests/modern_polars/ewm_mean_test.py +++ b/tests/modern_polars/ewm_mean_test.py @@ -7,11 +7,11 @@ def test_ew_mean( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() data = { @@ -41,7 +41,7 @@ def test_ew_mean( ], } - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) expr = ( nw.col("close") diff --git a/tests/modern_polars/filter_test.py b/tests/modern_polars/filter_test.py index a6a0664cf8..82e1c01c3b 100644 --- a/tests/modern_polars/filter_test.py +++ b/tests/modern_polars/filter_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, assert_equal_data -def test_filter(constructor: Constructor) -> None: +def test_filter(nw_frame_constructor: Constructor) -> None: data = { "time": [ "2021-01-01", @@ -34,7 +34,7 @@ def test_filter(constructor: Constructor) -> None: ], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) df = df.with_columns(nw.col("time").str.to_datetime(format="%Y-%m-%d")) diff --git a/tests/modern_polars/method_chaining_2_test.py b/tests/modern_polars/method_chaining_2_test.py index 58451e9f9a..bcd1d3f0a1 100644 --- a/tests/modern_polars/method_chaining_2_test.py +++ b/tests/modern_polars/method_chaining_2_test.py @@ -27,8 +27,8 @@ } -def test_filter_is_between(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_filter_is_between(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = ( df.select(nw.col(["flight_date", "tail_number", "dep_time", "dep_delay"])) .drop_nulls() diff --git a/tests/modern_polars/method_chaining_test.py b/tests/modern_polars/method_chaining_test.py index ba7a06b894..9f36e32409 100644 --- a/tests/modern_polars/method_chaining_test.py +++ b/tests/modern_polars/method_chaining_test.py @@ -30,20 +30,24 @@ } -def test_split_list_get(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(backend in str(constructor) for backend in ("dask",)): +def test_split_list_get( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(backend in str(nw_frame_constructor) for backend in ("dask",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor): + if "pandas" in str(nw_frame_constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if str(constructor).startswith("pandas") and "pyarrow" not in str(constructor): - df = nw.from_native(constructor(data)) + if str(nw_frame_constructor).startswith("pandas") and "pyarrow" not in str( + nw_frame_constructor + ): + df = nw.from_native(nw_frame_constructor(data)) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df.select(nw.col("OriginCityName").str.split(",").list.get(0)) return - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(nw.col("OriginCityName").str.split(",").list.get(0)) assert_equal_data(result, expected) diff --git a/tests/modern_polars/performance_test.py b/tests/modern_polars/performance_test.py index b765055cbd..04686aaad4 100644 --- a/tests/modern_polars/performance_test.py +++ b/tests/modern_polars/performance_test.py @@ -10,10 +10,12 @@ expected = {"weight_kg": [89, 38, 79, 68, 78, 33, 86]} -def test_parse_weight(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if any(x in str(constructor) for x in ("pyspark", "ibis", "duckdb")): +def test_parse_weight( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if any(x in str(nw_frame_constructor) for x in ("pyspark", "ibis", "duckdb")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) col = nw.col("weight") is_kg = col.str.ends_with("kg") diff --git a/tests/modern_polars/pivot_test.py b/tests/modern_polars/pivot_test.py index b6e6b16dde..c481258a02 100644 --- a/tests/modern_polars/pivot_test.py +++ b/tests/modern_polars/pivot_test.py @@ -9,11 +9,11 @@ def test_pivot( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): + if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): pytest.skip() data = { @@ -25,7 +25,7 @@ def test_pivot( "ticker": [*["AAPL", "TSLA", "MSFT", "NFLX"] * 3], "price": [100, 200, 300, 400, 110, 220, 330, 420, 105, 210, 315, 440], } - df = nw.from_native(constructor_eager(data), eager_only=True).sort("date") + df = nw.from_native(nw_eager_constructor(data), eager_only=True).sort("date") pivoted = df.pivot(index="date", values="price", on="ticker") diff --git a/tests/modern_polars/unpivot_test.py b/tests/modern_polars/unpivot_test.py index c5bff87dc6..69105641ea 100644 --- a/tests/modern_polars/unpivot_test.py +++ b/tests/modern_polars/unpivot_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, assert_equal_data -def test_unpivot(constructor: Constructor) -> None: +def test_unpivot(nw_frame_constructor: Constructor) -> None: data = { "date": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)], "aapl": [110, 100, 105], @@ -14,7 +14,7 @@ def test_unpivot(constructor: Constructor) -> None: "msft": [330, 300, 315], "nflx": [420, 400, 440], } - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.unpivot(index="date", value_name="price").sort(by=["date", "variable"]) expected = { "date": [ diff --git a/tests/namespace_test.py b/tests/namespace_test.py index e94a6690c1..ebb2ec9d17 100644 --- a/tests/namespace_test.py +++ b/tests/namespace_test.py @@ -70,9 +70,9 @@ def test_namespace_from_backend_name(backend: BackendName) -> None: assert namespace.version is Version.MAIN -def test_namespace_from_native_object(constructor: Constructor) -> None: +def test_namespace_from_native_object(nw_frame_constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6]} - frame = constructor(data) + frame = nw_frame_constructor(data) namespace = Namespace.from_native_object(frame) nw_frame = nw.from_native(frame) assert namespace.implementation == nw_frame.implementation diff --git a/tests/new_series_test.py b/tests/new_series_test.py index 9360ef6fdc..0aa33418f9 100644 --- a/tests/new_series_test.py +++ b/tests/new_series_test.py @@ -6,8 +6,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_new_series(constructor_eager: ConstructorEager) -> None: - s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] +def test_new_series(nw_eager_constructor: ConstructorEager) -> None: + s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] result = nw.new_series("b", [4, 1, 2], backend=nw.get_native_namespace(s)) expected = {"b": [4, 1, 2]} # all supported libraries auto-infer this to be int64, we can always special-case diff --git a/tests/preserve_pandas_like_columns_name_attr_test.py b/tests/preserve_pandas_like_columns_name_attr_test.py index 3127040bee..fec4d018a7 100644 --- a/tests/preserve_pandas_like_columns_name_attr_test.py +++ b/tests/preserve_pandas_like_columns_name_attr_test.py @@ -11,18 +11,20 @@ def test_ops_preserve_column_index_name( - constructor: Callable[..., pd.DataFrame], request: pytest.FixtureRequest + nw_frame_constructor: Callable[..., pd.DataFrame], request: pytest.FixtureRequest ) -> None: - if not any(x in str(constructor) for x in ("pandas", "modin", "cudf", "dask")): + if not any( + x in str(nw_frame_constructor) for x in ("pandas", "modin", "cudf", "dask") + ): pytest.skip( reason="Dataframe columns is a list and do not have a `name` like a pandas Index does" ) - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): # https://github.com/dask/dask/issues/11874 request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_native = constructor(data) + df_native = nw_frame_constructor(data) df_native.columns.name = "foo" df = nw.from_native(df_native) diff --git a/tests/read_scan_test.py b/tests/read_scan_test.py index 0e0c94d994..a0439aa88b 100644 --- a/tests/read_scan_test.py +++ b/tests/read_scan_test.py @@ -126,16 +126,16 @@ def test_read_csv_raise_with_lazy(backend: _LazyOnly) -> None: def test_scan_csv( - csv_path: FileSource, csv_path_sep: FileSource, constructor: Constructor + csv_path: FileSource, csv_path_sep: FileSource, nw_frame_constructor: Constructor ) -> None: kwargs: dict[str, Any] - if "sqlframe" in str(constructor): + if "sqlframe" in str(nw_frame_constructor): kwargs = {"session": sqlframe_session(), "inferSchema": True, "header": True} - elif "pyspark" in str(constructor): + elif "pyspark" in str(nw_frame_constructor): kwargs = {"session": pyspark_session(), "inferSchema": True, "header": True} else: kwargs = {} - backend = native_namespace(constructor) + backend = native_namespace(nw_frame_constructor) assert_equal_lazy(nw.scan_csv(csv_path, backend=backend, **kwargs)) assert_equal_lazy(nw.scan_csv(csv_path_sep, backend=backend, separator="|", **kwargs)) @@ -171,15 +171,17 @@ def test_read_parquet_raise_with_lazy(backend: _LazyOnly) -> None: @skipif_pandas_lt_1_5 -def test_scan_parquet(parquet_path: FileSource, constructor: Constructor) -> None: +def test_scan_parquet( + parquet_path: FileSource, nw_frame_constructor: Constructor +) -> None: kwargs: dict[str, Any] - if "sqlframe" in str(constructor): + if "sqlframe" in str(nw_frame_constructor): kwargs = {"session": sqlframe_session(), "inferSchema": True} - elif "pyspark" in str(constructor): + elif "pyspark" in str(nw_frame_constructor): kwargs = {"session": pyspark_session(), "inferSchema": True, "header": True} else: kwargs = {} - backend = native_namespace(constructor) + backend = native_namespace(nw_frame_constructor) assert_equal_lazy(nw.scan_parquet(parquet_path, backend=backend, **kwargs)) diff --git a/tests/selectors_test.py b/tests/selectors_test.py index 63c6b387e5..9cb7f153c4 100644 --- a/tests/selectors_test.py +++ b/tests/selectors_test.py @@ -27,73 +27,79 @@ data_regex = {"foo": ["x", "y"], "bar": [123, 456], "baz": [2.0, 5.5], "zap": [0, 1]} -def test_selectors(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_selectors(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(ncs.by_dtype([nw.Int64, nw.Float64]) + 1) expected = {"a": [2, 2, 3], "c": [5.1, 6.0, 7.0]} assert_equal_data(result, expected) -def test_matches(constructor: Constructor) -> None: - df = nw.from_native(constructor(data_regex)) +def test_matches(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data_regex)) result = df.select(ncs.matches("[^z]a") + 1) expected = {"bar": [124, 457], "baz": [3.0, 6.5]} assert_equal_data(result, expected) -def test_numeric(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_numeric(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(ncs.numeric() + 1) expected = {"a": [2, 2, 3], "c": [5.1, 6.0, 7.0]} assert_equal_data(result, expected) -def test_boolean(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_boolean(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(ncs.boolean()) expected = {"d": [True, False, True]} assert_equal_data(result, expected) -def test_string(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_string(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) result = df.select(ncs.string()) expected = {"b": ["a", "b", "c"]} assert_equal_data(result, expected) -def test_categorical(request: pytest.FixtureRequest, constructor: Constructor) -> None: - if "pyarrow_table_constructor" in str(constructor) and PYARROW_VERSION <= ( +def test_categorical( + request: pytest.FixtureRequest, nw_frame_constructor: Constructor +) -> None: + if "pyarrow_table_constructor" in str(nw_frame_constructor) and PYARROW_VERSION <= ( 15, ): # pragma: no cover request.applymarker(pytest.mark.xfail) if ( - "pyspark" in str(constructor) - or "duckdb" in str(constructor) - or "ibis" in str(constructor) + "pyspark" in str(nw_frame_constructor) + or "duckdb" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): request.applymarker(pytest.mark.xfail) expected = {"b": ["a", "b", "c"]} - df = nw.from_native(constructor(data)).with_columns(nw.col("b").cast(nw.Categorical)) + df = nw.from_native(nw_frame_constructor(data)).with_columns( + nw.col("b").cast(nw.Categorical) + ) result = df.select(ncs.categorical()) assert_equal_data(result, expected) -def test_datetime(constructor: Constructor, request: pytest.FixtureRequest) -> None: +def test_datetime( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: if ( - "pyspark" in str(constructor) - or "duckdb" in str(constructor) - or "dask" in str(constructor) - or ("pyarrow" in str(constructor) and is_windows()) - or ("pandas" in str(constructor) and PANDAS_VERSION < (2,)) - or "ibis" in str(constructor) + "pyspark" in str(nw_frame_constructor) + or "duckdb" in str(nw_frame_constructor) + or "dask" in str(nw_frame_constructor) + or ("pyarrow" in str(nw_frame_constructor) and is_windows()) + or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) + or "ibis" in str(nw_frame_constructor) # https://github.com/pola-rs/polars/issues/23767 # TODO(FBruzzesi): Manage polars version - or ("polars" in str(constructor) and POLARS_VERSION >= (1, 32, 0)) + or ("polars" in str(nw_frame_constructor) and POLARS_VERSION >= (1, 32, 0)) ): request.applymarker(pytest.mark.xfail) - if "modin" in str(constructor): + if "modin" in str(nw_frame_constructor): pytest.skip(reason="too slow") ts1 = datetime(2000, 11, 20, 18, 12, 16, 600000) @@ -102,7 +108,7 @@ def test_datetime(constructor: Constructor, request: pytest.FixtureRequest) -> N data = {"numeric": [3.14, 6.28], "ts": [ts1, ts2]} time_units: list[Literal["ns", "us", "ms", "s"]] = ["ms", "us", "ns"] - df = nw.from_native(constructor(data)).select( + df = nw.from_native(nw_frame_constructor(data)).select( nw.col("numeric"), *[ nw.col("ts").cast(nw.Datetime(time_unit=tu)).alias(f"ts_{tu}") @@ -184,13 +190,13 @@ def test_datetime(constructor: Constructor, request: pytest.FixtureRequest) -> N ).collect_schema().names() == ["ts_ms", "ts_us", "ts_utc"] -def test_datetime_no_tz(constructor: Constructor) -> None: +def test_datetime_no_tz(nw_frame_constructor: Constructor) -> None: ts1 = datetime(2000, 11, 20, 18, 12, 16, 600000) ts2 = datetime(2020, 10, 30, 10, 20, 25, 123000) data = {"numeric": [3.14, 6.28], "ts": [ts1, ts2]} - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) assert df.select(ncs.datetime()).collect_schema().names() == ["ts"] @@ -209,36 +215,36 @@ def test_datetime_no_tz(constructor: Constructor) -> None: ], ) def test_set_ops( - constructor: Constructor, + nw_frame_constructor: Constructor, selector: nw.selectors.Selector, expected: list[str], request: pytest.FixtureRequest, ) -> None: if ( - any(x in str(constructor) for x in ("duckdb", "sqlframe", "ibis")) + any(x in str(nw_frame_constructor) for x in ("duckdb", "sqlframe", "ibis")) and not expected ): # https://github.com/narwhals-dev/narwhals/issues/2469 request.applymarker(pytest.mark.xfail) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(selector).collect_schema().names() assert sorted(result) == expected -def test_subtract_expr(constructor: Constructor) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 27): +def test_subtract_expr(nw_frame_constructor: Constructor) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 27): # In old Polars versions, cs.numeric() - col('a') # would exclude column 'a' from the result, as opposed to # subtracting it. pytest.skip() - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) result = df.select(ncs.numeric() - nw.col("a")) expected = {"a": [0, 0, 0], "c": [3.1, 4.0, 4.0]} assert_equal_data(result, expected) -def test_set_ops_invalid(constructor: Constructor) -> None: - df = nw.from_native(constructor(data)) +def test_set_ops_invalid(nw_frame_constructor: Constructor) -> None: + df = nw.from_native(nw_frame_constructor(data)) with pytest.raises((NotImplementedError, ValueError)): df.select(1 - ncs.numeric()) with pytest.raises((NotImplementedError, ValueError)): @@ -254,20 +260,22 @@ def test_set_ops_invalid(constructor: Constructor) -> None: @pytest.mark.skipif(is_windows(), reason="windows is what it is") -def test_tz_aware(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "polars" in str(constructor) and POLARS_VERSION < (1, 19): +def test_tz_aware( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 19): # bug in old polars pytest.skip() if ( - "duckdb" in str(constructor) - or "pyspark" in str(constructor) - or "ibis" in str(constructor) + "duckdb" in str(nw_frame_constructor) + or "pyspark" in str(nw_frame_constructor) + or "ibis" in str(nw_frame_constructor) ): # replace_time_zone not implemented request.applymarker(pytest.mark.xfail) data = {"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)], "c": [4, 5]} - df = nw.from_native(constructor(data)).with_columns( + df = nw.from_native(nw_frame_constructor(data)).with_columns( b=nw.col("a").dt.replace_time_zone("Asia/Katmandu") ) result = df.select(nw.selectors.by_dtype(nw.Datetime)).collect_schema().names() diff --git a/tests/series_only/__contains___test.py b/tests/series_only/__contains___test.py index 13bc0eb4e0..6829192afb 100644 --- a/tests/series_only/__contains___test.py +++ b/tests/series_only/__contains___test.py @@ -17,25 +17,25 @@ ("other", "expected"), [(100, True), (None, True), (1, False), (100.314, False)] ) def test_contains( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, other: int | None, expected: bool, # noqa: FBT001 ) -> None: - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] assert (other in s) == expected @pytest.mark.parametrize("other", ["foo", [1, 2, 3]]) def test_contains_invalid_type( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager, other: Any + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager, other: Any ) -> None: - if "polars" not in str(constructor_eager) and "pyarrow_table" not in str( - constructor_eager + if "polars" not in str(nw_eager_constructor) and "pyarrow_table" not in str( + nw_eager_constructor ): request.applymarker(pytest.mark.xfail) - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] with pytest.raises(InvalidOperationError): _ = other in s diff --git a/tests/series_only/__iter___test.py b/tests/series_only/__iter___test.py index 5ed9e083f9..b00e6b18f8 100644 --- a/tests/series_only/__iter___test.py +++ b/tests/series_only/__iter___test.py @@ -15,11 +15,11 @@ def test_iter( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] assert isinstance(s, Iterable) assert_equal_data({"a": [x for x in s]}, {"a": [1, 2, 3]}) # noqa: C416 diff --git a/tests/series_only/alias_rename_test.py b/tests/series_only/alias_rename_test.py index e8420e8089..8ed8e8c657 100644 --- a/tests/series_only/alias_rename_test.py +++ b/tests/series_only/alias_rename_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_alias_rename(constructor_eager: ConstructorEager) -> None: +def test_alias_rename(nw_eager_constructor: ConstructorEager) -> None: data = [1, 2, 3] expected = {"bar": data} - series = nw.from_native(constructor_eager({"foo": data}), eager_only=True)["foo"] + series = nw.from_native(nw_eager_constructor({"foo": data}), eager_only=True)["foo"] result = series.alias("bar").to_frame() assert_equal_data(result, expected) result = series.rename("bar").to_frame() diff --git a/tests/series_only/arg_max_test.py b/tests/series_only/arg_max_test.py index c6460b7183..8bbc41a048 100644 --- a/tests/series_only/arg_max_test.py +++ b/tests/series_only/arg_max_test.py @@ -10,18 +10,18 @@ @pytest.mark.parametrize(("col", "expected"), [("a", 1), ("b", 2), ("z", 2)]) def test_arg_max_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, col: str, expected: float, request: pytest.FixtureRequest, ) -> None: - if "modin" in str(constructor_eager): + if "modin" in str(nw_eager_constructor): # TODO(unassigned): bug in modin? return - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # not implemented yet request.applymarker(pytest.mark.xfail) - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] series = nw.maybe_set_index(series, index=[1, 0, 9]) # type: ignore[arg-type] result = series.arg_max() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/series_only/arg_min_test.py b/tests/series_only/arg_min_test.py index 34a38a57f9..6e2b91e7ac 100644 --- a/tests/series_only/arg_min_test.py +++ b/tests/series_only/arg_min_test.py @@ -10,18 +10,18 @@ @pytest.mark.parametrize(("col", "expected"), [("a", 0), ("b", 0), ("z", 0)]) def test_arg_min_series( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, col: str, expected: float, request: pytest.FixtureRequest, ) -> None: - if "modin" in str(constructor_eager): + if "modin" in str(nw_eager_constructor): # TODO(unassigned): bug in modin? return - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # not implemented yet request.applymarker(pytest.mark.xfail) - series = nw.from_native(constructor_eager(data), eager_only=True)[col] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] series = nw.maybe_set_index(series, index=[1, 0, 9]) # type: ignore[arg-type] result = series.arg_min() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/series_only/arg_true_test.py b/tests/series_only/arg_true_test.py index ccc25a83e7..70dbad5e2a 100644 --- a/tests/series_only/arg_true_test.py +++ b/tests/series_only/arg_true_test.py @@ -4,8 +4,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_arg_true_series(constructor_eager: ConstructorEager) -> None: - df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}), eager_only=True) +def test_arg_true_series(nw_eager_constructor: ConstructorEager) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, None, None, 3]}), eager_only=True) result = df.select(df["a"].is_null().arg_true()) expected = {"a": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/series_only/array_dunder_test.py b/tests/series_only/array_dunder_test.py index b50d033aa2..57ed6db5e4 100644 --- a/tests/series_only/array_dunder_test.py +++ b/tests/series_only/array_dunder_test.py @@ -15,49 +15,49 @@ def test_array_dunder( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__() np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype="int64")) def test_array_dunder_with_dtype( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__(object) np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype=object)) def test_array_dunder_with_copy( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__(copy=True) np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype="int64")) - if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION < (3,): + if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < (3,): # If it's pandas, we know that `copy=False` definitely took effect. # So, let's check it! result = s.__array__(copy=False) diff --git a/tests/series_only/cast_test.py b/tests/series_only/cast_test.py index b646f38299..3db0300bf9 100644 --- a/tests/series_only/cast_test.py +++ b/tests/series_only/cast_test.py @@ -13,12 +13,12 @@ def test_cast_253( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): request.applymarker(pytest.mark.xfail) - df_raw = constructor_eager({"a": [1]}) + df_raw = nw_eager_constructor({"a": [1]}) result = nw.from_native(df_raw, eager_only=True).select( nw.col("a").cast(nw.String) + "hi" )["a"][0] @@ -111,16 +111,16 @@ def test_unknown_to_int() -> None: def test_cast_to_enum_vmain( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: # Backends that do not (yet) support Enum dtype if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("pyarrow_table", "sqlframe", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - df_nw = nw.from_native(constructor({"a": ["a", "b"]})) + df_nw = nw.from_native(nw_frame_constructor({"a": ["a", "b"]})) col_a = nw.col("a") with pytest.raises( diff --git a/tests/series_only/gather_every_test.py b/tests/series_only/gather_every_test.py index e7d55fb03c..11fe56702a 100644 --- a/tests/series_only/gather_every_test.py +++ b/tests/series_only/gather_every_test.py @@ -11,9 +11,9 @@ @pytest.mark.parametrize("n", [1, 2, 3]) @pytest.mark.parametrize("offset", [1, 2, 3]) def test_gather_every_series( - constructor_eager: ConstructorEager, n: int, offset: int + nw_eager_constructor: ConstructorEager, n: int, offset: int ) -> None: - series = nw.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.gather_every(n=n, offset=offset) expected = data["a"][offset::n] diff --git a/tests/series_only/getitem_test.py b/tests/series_only/getitem_test.py index aa63ac8414..ec62dcda27 100644 --- a/tests/series_only/getitem_test.py +++ b/tests/series_only/getitem_test.py @@ -11,9 +11,9 @@ from tests.utils import ConstructorEager -def test_by_slice(constructor_eager: ConstructorEager) -> None: +def test_by_slice(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) result = {"a": df["a"][[0, 1]]} expected = {"a": [1, 2]} assert_equal_data(result, expected) @@ -51,8 +51,8 @@ def test_getitem_arrow_scalar() -> None: assert isinstance(result, int) -def test_index(constructor_eager: ConstructorEager) -> None: - df = constructor_eager({"a": [0, 1, 2]}) +def test_index(nw_eager_constructor: ConstructorEager) -> None: + df = nw_eager_constructor({"a": [0, 1, 2]}) snw = nw.from_native(df, eager_only=True)["a"] assert snw[snw[0]] == 0 @@ -60,17 +60,17 @@ def test_index(constructor_eager: ConstructorEager) -> None: @pytest.mark.filterwarnings( "ignore:.*_array__ implementation doesn't accept a copy keyword.*:DeprecationWarning:modin" ) -def test_getitem_other_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager({"a": [1, None, 2, 3]}), eager_only=True)[ - "a" - ] - other = nw.from_native(constructor_eager({"b": [1, 3]}), eager_only=True)["b"] +def test_getitem_other_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native( + nw_eager_constructor({"a": [1, None, 2, 3]}), eager_only=True + )["a"] + other = nw.from_native(nw_eager_constructor({"b": [1, 3]}), eager_only=True)["b"] assert_equal_data(series[other].to_frame(), {"a": [None, 3]}) -def test_getitem_invalid_series(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager({"a": [1, None, 2, 3]}), eager_only=True)[ - "a" - ] +def test_getitem_invalid_series(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native( + nw_eager_constructor({"a": [1, None, 2, 3]}), eager_only=True + )["a"] with pytest.raises(TypeError, match="Unexpected type"): series[series > 1] diff --git a/tests/series_only/head_test.py b/tests/series_only/head_test.py index 5697bc59e5..e273245c54 100644 --- a/tests/series_only/head_test.py +++ b/tests/series_only/head_test.py @@ -7,8 +7,8 @@ @pytest.mark.parametrize("n", [2, -1]) -def test_head_series(constructor_eager: ConstructorEager, n: int) -> None: - df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) +def test_head_series(nw_eager_constructor: ConstructorEager, n: int) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) result = df.select(df["a"].head(n)) expected = {"a": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/series_only/hist_test.py b/tests/series_only/hist_test.py index 882c658f27..d75ed388a6 100644 --- a/tests/series_only/hist_test.py +++ b/tests/series_only/hist_test.py @@ -77,8 +77,8 @@ def maybe_name_to_constructor(name: str) -> ConstructorEager: def test_hist_bin( name: str, bins: list[float], expected: Sequence[float], *, include_breakpoint: bool ) -> None: - constructor_eager = maybe_name_to_constructor(name) - df = nw.from_native(constructor_eager(data)).with_columns( + nw_eager_constructor = maybe_name_to_constructor(name) + df = nw.from_native(nw_eager_constructor(data)).with_columns( float=nw.col("int").cast(nw.Float64) ) expected_full = {"count": expected} @@ -106,7 +106,7 @@ def test_hist_bin( # missing/nan results df = nw.from_native( - constructor_eager( + nw_eager_constructor( {"has_nan": [float("nan"), *data["int"]], "has_null": [None, *data["int"]]} ) ) @@ -124,8 +124,8 @@ def test_hist_bin( def test_hist_count( name: str, *, params: dict[str, Any], include_breakpoint: bool ) -> None: - constructor_eager = maybe_name_to_constructor(name) - df = nw.from_native(constructor_eager(data)).with_columns( + nw_eager_constructor = maybe_name_to_constructor(name) + df = nw.from_native(nw_eager_constructor(data)).with_columns( float=nw.col("int").cast(nw.Float64) ) bin_count = params["bin_count"] @@ -148,7 +148,7 @@ def test_hist_count( # missing/nan results df = nw.from_native( - constructor_eager( + nw_eager_constructor( {"has_nan": [float("nan"), *data["int"]], "has_null": [None, *data["int"]]} ) ) @@ -167,9 +167,9 @@ def test_hist_count( @param_name def test_hist_count_no_spread(name: str) -> None: - constructor_eager = maybe_name_to_constructor(name) + nw_eager_constructor = maybe_name_to_constructor(name) data = {"all_zero": [0, 0, 0], "all_non_zero": [5, 5, 5]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_eager_constructor(data)) result = df["all_zero"].hist(bin_count=4, include_breakpoint=True) expected = {"breakpoint": [-0.25, 0.0, 0.25, 0.5], "count": [0, 3, 0, 0]} @@ -199,8 +199,8 @@ def test_hist_bin_and_bin_count() -> None: @param_include_breakpoint @param_name def test_hist_no_data(name: str, *, include_breakpoint: bool) -> None: - constructor_eager = maybe_name_to_constructor(name) - s = nw.from_native(constructor_eager({"values": []})).select( + nw_eager_constructor = maybe_name_to_constructor(name) + s = nw.from_native(nw_eager_constructor({"values": []})).select( nw.col("values").cast(nw.Float64) )["values"] for bin_count in [1, 10]: @@ -221,8 +221,8 @@ def test_hist_no_data(name: str, *, include_breakpoint: bool) -> None: @param_name def test_hist_small_bins(name: str) -> None: - constructor_eager = maybe_name_to_constructor(name) - s = nw.from_native(constructor_eager({"values": [1, 2, 3]})) + nw_eager_constructor = maybe_name_to_constructor(name) + s = nw.from_native(nw_eager_constructor({"values": [1, 2, 3]})) result = s["values"].hist(bins=None, bin_count=None) assert len(result) == 10 @@ -230,11 +230,11 @@ def test_hist_small_bins(name: str) -> None: s["values"].hist(bins=[1, 3], bin_count=4) -def test_hist_non_monotonic(constructor_eager: ConstructorEager) -> None: - if "cudf" in str(constructor_eager): +def test_hist_non_monotonic(nw_eager_constructor: ConstructorEager) -> None: + if "cudf" in str(nw_eager_constructor): # TODO(unassigned): too many spurious failures, report and revisit return - df = nw.from_native(constructor_eager({"int": [0, 1, 2, 3, 4, 5, 6]})) + df = nw.from_native(nw_eager_constructor({"int": [0, 1, 2, 3, 4, 5, 6]})) with pytest.raises(ComputeError, match="monotonic"): df["int"].hist(bins=[5, 0, 2]) @@ -275,14 +275,14 @@ def test_hist_non_monotonic(constructor_eager: ConstructorEager) -> None: def test_hist_bin_hypotheis( name: str, data: list[float], bin_deltas: list[float] ) -> None: - constructor_eager = maybe_name_to_constructor(name) + nw_eager_constructor = maybe_name_to_constructor(name) pytest.importorskip("polars") import polars as pl - df = nw.from_native(constructor_eager({"values": data})).select( + df = nw.from_native(nw_eager_constructor({"values": data})).select( nw.col("values").cast(nw.Float64) ) - df_bins_native = constructor_eager({"bins": bin_deltas}) + df_bins_native = nw_eager_constructor({"bins": bin_deltas}) bins = ( nw.from_native(df_bins_native, eager_only=True) .get_column("bins") @@ -319,8 +319,8 @@ def test_hist_count_hypothesis( pytest.importorskip("polars") import polars as pl - constructor_eager = maybe_name_to_constructor(name) - df = nw.from_native(constructor_eager({"values": data})).select( + nw_eager_constructor = maybe_name_to_constructor(name) + df = nw.from_native(nw_eager_constructor({"values": data})).select( nw.col("values").cast(nw.Float64) ) @@ -344,7 +344,7 @@ def test_hist_count_hypothesis( if expected[ "count" ].sum() != expected_data.is_not_nan().sum() and "polars" not in str( - constructor_eager + nw_eager_constructor ): request.applymarker(pytest.mark.xfail) diff --git a/tests/series_only/is_empty_test.py b/tests/series_only/is_empty_test.py index cfdc8bd15d..17d1408c05 100644 --- a/tests/series_only/is_empty_test.py +++ b/tests/series_only/is_empty_test.py @@ -8,8 +8,8 @@ from tests.utils import ConstructorEager -def test_is_empty(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] +def test_is_empty(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] assert not series.is_empty() assert not series[:1].is_empty() assert len(series[:1]) == 1 diff --git a/tests/series_only/is_ordered_categorical_test.py b/tests/series_only/is_ordered_categorical_test.py index 8833957b1c..fd49cfd7b0 100644 --- a/tests/series_only/is_ordered_categorical_test.py +++ b/tests/series_only/is_ordered_categorical_test.py @@ -70,10 +70,10 @@ def test_is_ordered_categorical_pyarrow_string() -> None: def test_is_definitely_not_ordered_categorical( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, ) -> None: assert not nw.is_ordered_categorical( - nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] ) diff --git a/tests/series_only/is_sorted_test.py b/tests/series_only/is_sorted_test.py index 4efddf542f..7a1723425e 100644 --- a/tests/series_only/is_sorted_test.py +++ b/tests/series_only/is_sorted_test.py @@ -15,18 +15,20 @@ [(data, False, False), (data_sorted, False, True), (data_sorted, True, False)], ) def test_is_sorted( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, input_data: list[int], descending: bool, # noqa: FBT001 expected: bool, # noqa: FBT001 ) -> None: - series = nw.from_native(constructor_eager({"a": input_data}), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor({"a": input_data}), eager_only=True)["a"] result = series.is_sorted(descending=descending) assert_equal_data({"a": [result]}, {"a": [expected]}) -def test_is_sorted_invalid(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager({"a": data_sorted}), eager_only=True)["a"] +def test_is_sorted_invalid(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor({"a": data_sorted}), eager_only=True)[ + "a" + ] with pytest.raises(TypeError): series.is_sorted(descending="invalid_type") # type: ignore[arg-type] diff --git a/tests/series_only/item_test.py b/tests/series_only/item_test.py index 521ce5af55..d467563702 100644 --- a/tests/series_only/item_test.py +++ b/tests/series_only/item_test.py @@ -11,8 +11,8 @@ @pytest.mark.parametrize(("index", "expected"), [(0, 1), (1, 3)]) -def test_item(constructor_eager: ConstructorEager, index: int, expected: int) -> None: - series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] +def test_item(nw_eager_constructor: ConstructorEager, index: int, expected: int) -> None: + series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] result = series.item(index) assert_equal_data({"a": [result]}, {"a": [expected]}) assert_equal_data({"a": [series.head(1).item()]}, {"a": [1]}) @@ -24,7 +24,7 @@ def test_item(constructor_eager: ConstructorEager, index: int, expected: int) -> series.item(None) -def test_out_of_range(constructor_eager: ConstructorEager) -> None: - series = nw.from_native(constructor_eager({"a": [1, 2]}), eager_only=True)["a"] +def test_out_of_range(nw_eager_constructor: ConstructorEager) -> None: + series = nw.from_native(nw_eager_constructor({"a": [1, 2]}), eager_only=True)["a"] with pytest.raises(IndexError, match="out of range"): series.item(2) diff --git a/tests/series_only/scatter_test.py b/tests/series_only/scatter_test.py index d608f78f1a..afa703dacd 100644 --- a/tests/series_only/scatter_test.py +++ b/tests/series_only/scatter_test.py @@ -39,9 +39,9 @@ def test_scatter( indices: int | Collection[int], values: int | Collection[int], expected: list[Any], - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, ) -> None: - constructor = partial(series, constructor_eager) + constructor = partial(series, nw_eager_constructor) s = constructor("s", data) df = s.to_frame().with_row_index("dont change me") unchanged_indexed = df.to_dict(as_series=False) @@ -63,8 +63,8 @@ def test_scatter_pandas_index() -> None: pd.testing.assert_series_equal(result.to_native(), expected) -def test_scatter_2862(constructor_eager: ConstructorEager) -> None: - s = series(constructor_eager, "a", [1, 2, 3]) +def test_scatter_2862(nw_eager_constructor: ConstructorEager) -> None: + s = series(nw_eager_constructor, "a", [1, 2, 3]) assert_equal_series(s.scatter(1, 999), [1, 999, 3], "a") assert_equal_series(s.scatter([0, 2], [999, 888]), [999, 2, 888], "a") assert_equal_series(s.scatter([2, 0], [999, 888]), [888, 2, 999], "a") diff --git a/tests/series_only/shape_test.py b/tests/series_only/shape_test.py index 8f8ba638e5..3863671bf6 100644 --- a/tests/series_only/shape_test.py +++ b/tests/series_only/shape_test.py @@ -8,7 +8,9 @@ from tests.utils import ConstructorEager -def test_shape(constructor_eager: ConstructorEager) -> None: - result = nw.from_native(constructor_eager({"a": [1, 2]}), eager_only=True)["a"].shape +def test_shape(nw_eager_constructor: ConstructorEager) -> None: + result = nw.from_native(nw_eager_constructor({"a": [1, 2]}), eager_only=True)[ + "a" + ].shape expected = (2,) assert result == expected diff --git a/tests/series_only/sort_test.py b/tests/series_only/sort_test.py index 8b74c6623b..a6f2d9c181 100644 --- a/tests/series_only/sort_test.py +++ b/tests/series_only/sort_test.py @@ -21,11 +21,14 @@ ], ) def test_sort_series( - constructor_eager: ConstructorEager, descending: Any, nulls_last: Any, expected: Any + nw_eager_constructor: ConstructorEager, + descending: Any, + nulls_last: Any, + expected: Any, ) -> None: - series = nw.from_native(constructor_eager({"a": [1, 3, 2, None]}), eager_only=True)[ - "a" - ] + series = nw.from_native( + nw_eager_constructor({"a": [1, 3, 2, None]}), eager_only=True + )["a"] result = series.sort(descending=descending, nulls_last=nulls_last) assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/series_only/tail_test.py b/tests/series_only/tail_test.py index 43f9866094..8e1de08e44 100644 --- a/tests/series_only/tail_test.py +++ b/tests/series_only/tail_test.py @@ -7,8 +7,8 @@ @pytest.mark.parametrize("n", [2, -1]) -def test_tail_series(constructor_eager: ConstructorEager, n: int) -> None: - df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) +def test_tail_series(nw_eager_constructor: ConstructorEager, n: int) -> None: + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) result = df.select(df["a"].tail(n)) expected = {"a": [2, 3]} assert_equal_data(result, expected) diff --git a/tests/series_only/to_arrow_test.py b/tests/series_only/to_arrow_test.py index 6675ea2e31..64eb345b88 100644 --- a/tests/series_only/to_arrow_test.py +++ b/tests/series_only/to_arrow_test.py @@ -14,9 +14,9 @@ from tests.utils import ConstructorEager -def test_to_arrow(constructor_eager: ConstructorEager) -> None: +def test_to_arrow(nw_eager_constructor: ConstructorEager) -> None: data = [1, 2, 3] - result = nw.from_native(constructor_eager({"a": data}), eager_only=True)[ + result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ "a" ].to_arrow() @@ -25,16 +25,16 @@ def test_to_arrow(constructor_eager: ConstructorEager) -> None: def test_to_arrow_with_nulls( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pandas_constructor" in str(constructor_eager) or "modin_constructor" in str( - constructor_eager + if "pandas_constructor" in str(nw_eager_constructor) or "modin_constructor" in str( + nw_eager_constructor ): request.applymarker(pytest.mark.xfail) data = [1, 2, None] result = ( - nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] .cast(nw.Int64) .to_arrow() ) diff --git a/tests/series_only/to_dummy_test.py b/tests/series_only/to_dummy_test.py index df301a6978..d3d04cdbda 100644 --- a/tests/series_only/to_dummy_test.py +++ b/tests/series_only/to_dummy_test.py @@ -10,8 +10,8 @@ @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies(constructor_eager: ConstructorEager, sep: str) -> None: - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias("a") +def test_to_dummies(nw_eager_constructor: ConstructorEager, sep: str) -> None: + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].alias("a") result = s.to_dummies(separator=sep) expected = {f"a{sep}x": [1, 0, 0], f"a{sep}y": [0, 1, 0], f"a{sep}z": [0, 0, 1]} @@ -19,8 +19,8 @@ def test_to_dummies(constructor_eager: ConstructorEager, sep: str) -> None: @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_drop_first(constructor_eager: ConstructorEager, sep: str) -> None: - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias("a") +def test_to_dummies_drop_first(nw_eager_constructor: ConstructorEager, sep: str) -> None: + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].alias("a") result = s.to_dummies(drop_first=True, separator=sep) expected = {f"a{sep}y": [0, 1, 0], f"a{sep}z": [0, 0, 1]} @@ -28,10 +28,12 @@ def test_to_dummies_drop_first(constructor_eager: ConstructorEager, sep: str) -> @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_with_nulls(constructor_eager: ConstructorEager, sep: str) -> None: - if "pandas_nullable_constructor" not in str(constructor_eager): +def test_to_dummies_with_nulls(nw_eager_constructor: ConstructorEager, sep: str) -> None: + if "pandas_nullable_constructor" not in str(nw_eager_constructor): pytest.skip() - s = nw.from_native(constructor_eager({"a": data_na}), eager_only=True)["a"].alias("a") + s = nw.from_native(nw_eager_constructor({"a": data_na}), eager_only=True)["a"].alias( + "a" + ) result = s.to_dummies(separator=sep) expected = {f"a{sep}null": [0, 0, 1], f"a{sep}x": [1, 0, 0], f"a{sep}y": [0, 1, 0]} @@ -39,8 +41,12 @@ def test_to_dummies_with_nulls(constructor_eager: ConstructorEager, sep: str) -> @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_drop_first_na(constructor_eager: ConstructorEager, sep: str) -> None: - s = nw.from_native(constructor_eager({"a": data_na}), eager_only=True)["a"].alias("a") +def test_to_dummies_drop_first_na( + nw_eager_constructor: ConstructorEager, sep: str +) -> None: + s = nw.from_native(nw_eager_constructor({"a": data_na}), eager_only=True)["a"].alias( + "a" + ) result = s.to_dummies(drop_first=True, separator=sep) expected = {f"a{sep}null": [0, 0, 1], f"a{sep}y": [0, 1, 0]} diff --git a/tests/series_only/to_frame_test.py b/tests/series_only/to_frame_test.py index 8f56f7f6fa..1310d69668 100644 --- a/tests/series_only/to_frame_test.py +++ b/tests/series_only/to_frame_test.py @@ -6,9 +6,9 @@ data = [1, 2, 3] -def test_to_frame(constructor_eager: ConstructorEager) -> None: +def test_to_frame(nw_eager_constructor: ConstructorEager) -> None: df = ( - nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] .alias("") .to_frame() ) diff --git a/tests/series_only/to_list_test.py b/tests/series_only/to_list_test.py index e532f54799..c573f3087f 100644 --- a/tests/series_only/to_list_test.py +++ b/tests/series_only/to_list_test.py @@ -6,6 +6,6 @@ data = [1, 2, 3] -def test_to_list(constructor_eager: ConstructorEager) -> None: - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] +def test_to_list(nw_eager_constructor: ConstructorEager) -> None: + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] assert_equal_data({"a": s.to_list()}, {"a": [1, 2, 3]}) diff --git a/tests/series_only/to_native_test.py b/tests/series_only/to_native_test.py index 350d81764d..b5fc3c13ff 100644 --- a/tests/series_only/to_native_test.py +++ b/tests/series_only/to_native_test.py @@ -10,8 +10,8 @@ data = [4, 4, 4, 1, 6, 6, 4, 4, 1, 1] -def test_to_native(constructor_eager: ConstructorEager) -> None: - orig_series = constructor_eager({"a": data})["a"] # type: ignore[index] - nw_series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] +def test_to_native(nw_eager_constructor: ConstructorEager) -> None: + orig_series = nw_eager_constructor({"a": data})["a"] # type: ignore[index] + nw_series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] result = nw_series.to_native() assert isinstance(result, orig_series.__class__) diff --git a/tests/series_only/to_numpy_test.py b/tests/series_only/to_numpy_test.py index 21873760cb..10dbfc7e0d 100644 --- a/tests/series_only/to_numpy_test.py +++ b/tests/series_only/to_numpy_test.py @@ -17,15 +17,15 @@ def test_to_numpy( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pandas_constructor" in str(constructor_eager) or "modin_constructor" in str( - constructor_eager + if "pandas_constructor" in str(nw_eager_constructor) or "modin_constructor" in str( + nw_eager_constructor ): request.applymarker(pytest.mark.xfail) data = [1, 2, None] - s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].cast( + s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].cast( nw.Int64 ) assert s.to_numpy().dtype == "float64" @@ -35,17 +35,17 @@ def test_to_numpy( def test_to_numpy_tz_aware( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) - or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) - or ("pyarrow" in str(constructor_eager) and is_windows()) + ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) + or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) + or ("pyarrow" in str(nw_eager_constructor) and is_windows()) ): request.applymarker(pytest.mark.xfail) request.applymarker(pytest.mark.xfail) df = nw.from_native( - constructor_eager({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), + nw_eager_constructor({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), eager_only=True, ) df = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) diff --git a/tests/series_only/to_pandas_test.py b/tests/series_only/to_pandas_test.py index 95cd969f14..8c0c0d5773 100644 --- a/tests/series_only/to_pandas_test.py +++ b/tests/series_only/to_pandas_test.py @@ -19,19 +19,19 @@ @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pyarrow") def test_convert( - request: pytest.FixtureRequest, constructor_eager: ConstructorEager + request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager ) -> None: pytest.importorskip("pyarrow") if any( - cname in str(constructor_eager) + cname in str(nw_eager_constructor) for cname in ("pandas_nullable", "pandas_pyarrow", "modin_pyarrow") ): request.applymarker(pytest.mark.xfail) - series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias( + series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ "a" - ) + ].alias("a") result = series.to_pandas() assert_series_equal(result, pd.Series([1, 3, 2], name="a")) diff --git a/tests/series_only/to_polars_test.py b/tests/series_only/to_polars_test.py index c99d6e889e..119d24300a 100644 --- a/tests/series_only/to_polars_test.py +++ b/tests/series_only/to_polars_test.py @@ -15,12 +15,12 @@ data = [1, 3, 2] -def test_series_to_polars(constructor_eager: ConstructorEager) -> None: +def test_series_to_polars(nw_eager_constructor: ConstructorEager) -> None: pytest.importorskip("pyarrow") from polars.testing import assert_series_equal result = ( - nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] + nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] .alias("a") .to_polars() ) diff --git a/tests/series_only/value_counts_test.py b/tests/series_only/value_counts_test.py index 77a7656cf2..4e730f1d28 100644 --- a/tests/series_only/value_counts_test.py +++ b/tests/series_only/value_counts_test.py @@ -14,11 +14,11 @@ @pytest.mark.parametrize("name", [None, "count_name"]) def test_value_counts( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, normalize: Any, name: str | None, ) -> None: - if "pandas_nullable_constructor" in str(constructor_eager) and PANDAS_VERSION < ( + if "pandas_nullable_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < ( 2, 2, ): @@ -34,9 +34,9 @@ def test_value_counts( expected_name = name or ("proportion" if normalize else "count") expected = {"a": expected_index, expected_name: expected_count} - series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias( + series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ "a" - ) + ].alias("a") sorted_result = series.value_counts(sort=True, name=name, normalize=normalize) assert_equal_data(sorted_result, expected) diff --git a/tests/series_only/zip_with_test.py b/tests/series_only/zip_with_test.py index b40ac19fd6..f0f7e40331 100644 --- a/tests/series_only/zip_with_test.py +++ b/tests/series_only/zip_with_test.py @@ -4,22 +4,22 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_zip_with(constructor_eager: ConstructorEager) -> None: - series1 = nw.from_native(constructor_eager({"a": [1, 3, 2]}), eager_only=True)["a"] - series2 = nw.from_native(constructor_eager({"a": [4, 4, 6]}), eager_only=True)["a"] - mask = nw.from_native(constructor_eager({"a": [True, False, True]}), eager_only=True)[ - "a" - ] +def test_zip_with(nw_eager_constructor: ConstructorEager) -> None: + series1 = nw.from_native(nw_eager_constructor({"a": [1, 3, 2]}), eager_only=True)["a"] + series2 = nw.from_native(nw_eager_constructor({"a": [4, 4, 6]}), eager_only=True)["a"] + mask = nw.from_native( + nw_eager_constructor({"a": [True, False, True]}), eager_only=True + )["a"] result = series1.zip_with(mask, series2) expected = [1, 4, 2] assert_equal_data({"a": result}, {"a": expected}) -def test_zip_with_length_1(constructor_eager: ConstructorEager) -> None: - series1 = nw.from_native(constructor_eager({"a": [1]}), eager_only=True)["a"] - series2 = nw.from_native(constructor_eager({"a": [4]}), eager_only=True)["a"] - mask = nw.from_native(constructor_eager({"a": [False]}), eager_only=True)["a"] +def test_zip_with_length_1(nw_eager_constructor: ConstructorEager) -> None: + series1 = nw.from_native(nw_eager_constructor({"a": [1]}), eager_only=True)["a"] + series2 = nw.from_native(nw_eager_constructor({"a": [4]}), eager_only=True)["a"] + mask = nw.from_native(nw_eager_constructor({"a": [False]}), eager_only=True)["a"] result = series1.zip_with(mask, series2) expected = [4] diff --git a/tests/testing/assert_frame_equal_test.py b/tests/testing/assert_frame_equal_test.py index 9b0f813b2f..4f7fc4c023 100644 --- a/tests/testing/assert_frame_equal_test.py +++ b/tests/testing/assert_frame_equal_test.py @@ -22,9 +22,9 @@ def _assertion_error(detail: str) -> pytest.RaisesExc: return pytest.raises(AssertionError, match=re.escape(msg)) -def test_check_narwhals_objects(constructor: Constructor) -> None: +def test_check_narwhals_objects(nw_frame_constructor: Constructor) -> None: """Test that a type error is raised if the input is not a Narwhals object.""" - frame = constructor({"a": [1, 2, 3]}) + frame = nw_frame_constructor({"a": [1, 2, 3]}) msg = re.escape( "Expected `narwhals.DataFrame` or `narwhals.LazyFrame` instance, found" ) @@ -46,13 +46,13 @@ def test_implementation_mismatch() -> None: ) -def test_check_same_input_type(constructor_eager: ConstructorEager) -> None: +def test_check_same_input_type(nw_eager_constructor: ConstructorEager) -> None: """Test that left and right frames are either both eager or both lazy. - NOTE: Use `constructor_eager` instead of `constructor` so that the roundtrip + NOTE: Use `nw_eager_constructor` instead of `constructor` so that the roundtrip `.lazy().collect()` preserves the same implementation (and we raise the check after) """ - frame = nw.from_native(constructor_eager({"a": [1, 2, 3]})) + frame = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) msg = re.escape("inputs are different (unexpected input types)") with pytest.raises(AssertionError, match=msg): @@ -148,7 +148,7 @@ def test_check_same_input_type(constructor_eager: ConstructorEager) -> None: ], ) def test_check_schema_mismatch( - constructor: Constructor, + nw_frame_constructor: Constructor, left_schema: IntoSchema, right_schema: IntoSchema, *, @@ -157,10 +157,10 @@ def test_check_schema_mismatch( context: AbstractContextManager[Any], ) -> None: data = {"a": [1, 2, 3], "b": [4.5, 6.7, 8.9], "z": ["foo", "bar", "baz"]} - left = nw.from_native(constructor(data)).select( + left = nw.from_native(nw_frame_constructor(data)).select( nw.col(name).cast(dtype) for name, dtype in left_schema.items() ) - right = nw.from_native(constructor(data)).select( + right = nw.from_native(nw_frame_constructor(data)).select( nw.col(name).cast(dtype) for name, dtype in right_schema.items() ) @@ -170,9 +170,9 @@ def test_check_schema_mismatch( ) -def test_height_mismatch(constructor: Constructor) -> None: - left = nw.from_native(constructor({"a": [1, 2, 3]})) - right = nw.from_native(constructor({"a": [1, 3]})) +def test_height_mismatch(nw_frame_constructor: Constructor) -> None: + left = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) + right = nw.from_native(nw_frame_constructor({"a": [1, 3]})) with _assertion_error("height (row count) mismatch"): assert_frame_equal(left, right) @@ -180,15 +180,18 @@ def test_height_mismatch(constructor: Constructor) -> None: @pytest.mark.parametrize("check_row_order", [True, False]) def test_check_row_order( - constructor: Constructor, request: pytest.FixtureRequest, *, check_row_order: bool + nw_frame_constructor: Constructor, + request: pytest.FixtureRequest, + *, + check_row_order: bool, ) -> None: - if "pandas" in str(constructor): # pragma: no cover + if "pandas" in str(nw_frame_constructor): # pragma: no cover if PANDAS_VERSION < (2, 2): reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "Unsupported List type" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -196,10 +199,14 @@ def test_check_row_order( b_expr = nw.col("b").cast(nw.List(nw.String())) left = ( - nw.from_native(constructor(data)).with_columns(b_expr).sort("a", descending=False) + nw.from_native(nw_frame_constructor(data)) + .with_columns(b_expr) + .sort("a", descending=False) ) right = ( - nw.from_native(constructor(data)).with_columns(b_expr).sort("a", descending=True) + nw.from_native(nw_frame_constructor(data)) + .with_columns(b_expr) + .sort("a", descending=True) ) context = ( @@ -213,41 +220,44 @@ def test_check_row_order( def test_check_row_order_nested_only( - constructor: Constructor, request: pytest.FixtureRequest + nw_frame_constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pandas" in str(constructor): # pragma: no cover + if "pandas" in str(nw_frame_constructor): # pragma: no cover if PANDAS_VERSION < (2, 2): reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "dask" in str(constructor): + if "dask" in str(nw_frame_constructor): reason = "Unsupported List type" request.applymarker(pytest.mark.xfail(reason=reason)) data = {"b": [["x", "y"], ["x", "z"]]} b_expr = nw.col("b").cast(nw.List(nw.String())) - left = nw.from_native(constructor(data)).select(b_expr) + left = nw.from_native(nw_frame_constructor(data)).select(b_expr) msg = "`check_row_order=False` is not supported (yet) with only nested data type." with pytest.raises(NotImplementedError, match=re.escape(msg)): assert_frame_equal(left, left, check_row_order=False) -def test_self_equal(constructor: Constructor, testing_data: Data) -> None: +def test_self_equal(nw_frame_constructor: Constructor, testing_data: Data) -> None: """Test that a dataframe is equal to itself, including nested dtypes with nulls. We are dropping columns which type is unsupported by _some_ backend. """ cols_to_drop = ("categorical", "enum", "duration", "struct", "time") - if "pandas" in str(constructor) and PANDAS_VERSION < (2, 2): # pragma: no cover + if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < ( + 2, + 2, + ): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) _data = {k: v for k, v in testing_data.items() if k not in cols_to_drop} - df = nw.from_native(constructor(_data)) + df = nw.from_native(nw_frame_constructor(_data)) assert_frame_equal(df, df) # Keep to cover early return when no rows present but same schema diff --git a/tests/testing/assert_series_equal_test.py b/tests/testing/assert_series_equal_test.py index c4826c695e..0ee028917e 100644 --- a/tests/testing/assert_series_equal_test.py +++ b/tests/testing/assert_series_equal_test.py @@ -32,21 +32,21 @@ def series_from_native(native: IntoSeriesT) -> nw.Series[IntoSeriesT]: def test_self_equal( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, testing_data: Data, testing_schema: IntoSchema, ) -> None: """Test that a series is equal to itself, including nested dtypes with nulls.""" - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): # TODO(FBruzzesi): Investigate which conversion is failing aside from nested dtypes request.applymarker(pytest.mark.xfail) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 15, 0, ): # pragma: no cover @@ -56,7 +56,7 @@ def test_self_equal( ) pytest.skip(reason=reason) - if "pyarrow_table" in str(constructor_eager): + if "pyarrow_table" in str(nw_eager_constructor): # Replace Enum with Categorical, since Pyarrow does not support Enum data = dict(testing_data) schema = {**testing_schema, "enum": nw.Categorical()} @@ -64,7 +64,7 @@ def test_self_equal( data = dict(testing_data) schema = dict(testing_schema) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) for name, dtype in schema.items(): assert_series_equal(df[name].cast(dtype), df[name].cast(dtype)) @@ -93,10 +93,10 @@ def test_implementation_mismatch() -> None: ], ) def test_metadata_checks( - constructor_eager: ConstructorEager, setup_fn: SetupFn, error_msg: str + nw_eager_constructor: ConstructorEager, setup_fn: SetupFn, error_msg: str ) -> None: """Test metadata validation (length, dtype, name).""" - series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] left, right = setup_fn(series) with _assertion_error(error_msg): @@ -112,7 +112,7 @@ def test_metadata_checks( ], ) def test_metadata_checks_with_flags( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, setup_fn: SetupFn, error_msg: str, *, @@ -120,7 +120,7 @@ def test_metadata_checks_with_flags( check_names: bool, ) -> None: """Test the effect of check_dtypes and check_names flags.""" - series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] left, right = setup_fn(series) with _assertion_error(error_msg): @@ -142,25 +142,25 @@ def test_metadata_checks_with_flags( ) def test_check_order( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, dtype: nw.dtypes.DType, *, check_order: bool, context: AbstractContextManager[Any], ) -> None: """Test check_order behavior with nested and simple data.""" - if "cudf" in str(constructor_eager) and dtype.is_nested(): + if "cudf" in str(nw_eager_constructor) and dtype.is_nested(): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2) and dtype.is_nested(): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") data: list[Any] = [[1, 2, 3]] if dtype.is_nested() else [1, 2, 3] - frame = nw.from_native(constructor_eager({"a": data}), eager_only=True) + frame = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True) left = right = frame["a"].cast(dtype) with context: @@ -174,9 +174,9 @@ def test_check_order( {"left": ["x", None, None], "right": [None, "x", "y"]}, # Different null counts ], ) -def test_null_mismatch(constructor_eager: ConstructorEager, null_data: Data) -> None: +def test_null_mismatch(nw_eager_constructor: ConstructorEager, null_data: Data) -> None: """Test null value mismatch detection.""" - frame = nw.from_native(constructor_eager(null_data), eager_only=True) + frame = nw.from_native(nw_eager_constructor(null_data), eager_only=True) left, right = frame["left"], frame["right"] with _assertion_error("null value mismatch"): assert_series_equal(left, right, check_names=False) @@ -191,7 +191,7 @@ def test_null_mismatch(constructor_eager: ConstructorEager, null_data: Data) -> ], ) def test_numeric( - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, *, check_exact: bool, abs_tol: float, @@ -203,7 +203,7 @@ def test_numeric( "right": [1.01, float("nan"), float("inf"), None, 1.11], } - frame = nw.from_native(constructor_eager(data), eager_only=True) + frame = nw.from_native(nw_eager_constructor(data), eager_only=True) left, right = frame["left"], frame["right"] with context: assert_series_equal( @@ -259,7 +259,7 @@ def test_numeric( ) def test_list_like( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, l_vals: list[list[Any]], r_vals: list[list[Any]], *, @@ -267,18 +267,18 @@ def test_list_like( context: AbstractContextManager[Any], dtype: nw.dtypes.DType, ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") if ( - "pyarrow_table" in str(constructor_eager) + "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < (14, 0) and dtype == nw.Array ): # pragma: no cover @@ -289,7 +289,7 @@ def test_list_like( pytest.skip(reason=reason) data = {"left": l_vals, "right": r_vals} - frame = nw.from_native(constructor_eager(data), eager_only=True) + frame = nw.from_native(nw_eager_constructor(data), eager_only=True) left, right = frame["left"].cast(dtype), frame["right"].cast(dtype) with context: assert_series_equal(left, right, check_names=False, check_exact=check_exact) @@ -320,18 +320,18 @@ def test_list_like( ) def test_struct( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, l_vals: list[dict[str, Any]], r_vals: list[dict[str, Any]], *, check_exact: bool, context: AbstractContextManager[Any], ) -> None: - if "cudf" in str(constructor_eager): + if "cudf" in str(nw_eager_constructor): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(constructor_eager): + if "pandas" in str(nw_eager_constructor): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) @@ -339,7 +339,7 @@ def test_struct( dtype = nw.Struct({"a": nw.Float32(), "b": nw.List(nw.String())}) data = {"left": l_vals, "right": r_vals} - frame = nw.from_native(constructor_eager(data), eager_only=True) + frame = nw.from_native(nw_eager_constructor(data), eager_only=True) left, right = frame["left"].cast(dtype), frame["right"].cast(dtype) with context: assert_series_equal(left, right, check_names=False, check_exact=check_exact) @@ -374,13 +374,13 @@ def test_non_nw_series() -> None: ) def test_categorical_as_str( request: pytest.FixtureRequest, - constructor_eager: ConstructorEager, + nw_eager_constructor: ConstructorEager, *, categorical_as_str: bool, context: AbstractContextManager[Any], ) -> None: if ( - "polars" in str(constructor_eager) + "polars" in str(nw_eager_constructor) and POLARS_VERSION >= (1, 32) and not categorical_as_str ): @@ -388,11 +388,11 @@ def test_categorical_as_str( # exists but it does nothing in python. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(constructor_eager) and not categorical_as_str: + if "pyarrow_table" in str(nw_eager_constructor) and not categorical_as_str: # pyarrow dictionary dtype compares values, not the encoding. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( + if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( 15, 0, ): # pragma: no cover @@ -406,7 +406,7 @@ def test_categorical_as_str( "left": ["beluga", "dolphin", "narwhal", "orca"], "right": ["unicorn", "orca", "narwhal", "orca"], } - frame = nw.from_native(constructor_eager(data), eager_only=True) + frame = nw.from_native(nw_eager_constructor(data), eager_only=True) left = frame["left"].cast(nw.Categorical())[2:] right = frame["right"].cast(nw.Categorical())[2:] diff --git a/tests/testing/plugin_test.py b/tests/testing/plugin_test.py index 2205ac0f20..622ef6a19c 100644 --- a/tests/testing/plugin_test.py +++ b/tests/testing/plugin_test.py @@ -5,7 +5,7 @@ pytest_plugins = ["pytester"] -def test_constructor_eager_fixture_runs_for_each_backend( +def test_nw_eager_constructor_fixture_runs_for_each_backend( pytester: pytest.Pytester, ) -> None: pytest.importorskip("pandas") @@ -17,12 +17,12 @@ def test_constructor_eager_fixture_runs_for_each_backend( import narwhals as nw from narwhals.testing.typing import EagerFrameConstructor - def test_shape(constructor_eager: EagerFrameConstructor) -> None: - df = nw.from_native(constructor_eager({"x": [1, 2, 3]}), eager_only=True) + def test_shape(nw_eager_constructor: EagerFrameConstructor) -> None: + df = nw.from_native(nw_eager_constructor({"x": [1, 2, 3]}), eager_only=True) assert df.shape == (3, 1) """) result = pytester.runpytest_subprocess( - "-v", "-p", "no:randomly", "--constructors=pandas,polars[eager],pyarrow" + "-v", "-p", "no:randomly", "--nw-backends=pandas,polars[eager],pyarrow" ) result.assert_outcomes(passed=3) result.stdout.fnmatch_lines( @@ -44,12 +44,12 @@ def test_constructor_fixture_includes_lazy_backends(pytester: pytest.Pytester) - import narwhals as nw from narwhals.testing.typing import FrameConstructor - def test_columns(constructor: FrameConstructor) -> None: - df = nw.from_native(constructor({"x": [1, 2, 3]})) + def test_columns(nw_frame_constructor: FrameConstructor) -> None: + df = nw.from_native(nw_frame_constructor({"x": [1, 2, 3]})) assert df.collect_schema().names() == ["x"] """) result = pytester.runpytest_subprocess( - "-v", "--constructors=pandas,polars[lazy],duckdb" + "-v", "--nw-backends=pandas,polars[lazy],duckdb" ) result.assert_outcomes(passed=3) @@ -59,9 +59,9 @@ def test_external_constructor_disables_parametrisation(pytester: pytest.Pytester pytester.makepyfile(""" from narwhals.testing.typing import EagerFrameConstructor - def test_unparam(constructor_eager: EagerFrameConstructor) -> None: + def test_unparam(nw_eager_constructor: EagerFrameConstructor) -> None: pass """) - result = pytester.runpytest_subprocess("--use-external-constructor") + result = pytester.runpytest_subprocess("--use-external-nw-backend") # Without external parametrisation in place, the fixture is missing. result.assert_outcomes(errors=1) diff --git a/tests/translate/from_native_test.py b/tests/translate/from_native_test.py index a0d94b99fb..5fcd2076ff 100644 --- a/tests/translate/from_native_test.py +++ b/tests/translate/from_native_test.py @@ -507,8 +507,13 @@ def test_from_native_roundtrip_identity(native: Any, kwds: dict[str, Any]) -> No assert roundtrip is native -def test_pyspark_connect_deps_2517(constructor: Constructor) -> None: # pragma: no cover - if not ("pyspark" in str(constructor) and "sqlframe" not in str(constructor)): +def test_pyspark_connect_deps_2517( + nw_frame_constructor: Constructor, +) -> None: # pragma: no cover + if not ( + "pyspark" in str(nw_frame_constructor) + and "sqlframe" not in str(nw_frame_constructor) + ): # Only run this slow test if `--constructors=pyspark` is passed return pytest.importorskip("pyspark") @@ -524,11 +529,13 @@ def test_pyspark_connect_deps_2517(constructor: Constructor) -> None: # pragma: nw.from_native(spark.createDataFrame([(1,)], ["a"])) -def test_eager_only_pass_through_main(constructor: Constructor) -> None: - if not any(s in str(constructor) for s in ("pyspark", "dask", "ibis", "duckdb")): +def test_eager_only_pass_through_main(nw_frame_constructor: Constructor) -> None: + if not any( + s in str(nw_frame_constructor) for s in ("pyspark", "dask", "ibis", "duckdb") + ): pytest.skip(reason="Non lazy or polars") - df = constructor(data) + df = nw_frame_constructor(data) r1 = nw.from_native(df, eager_only=False, pass_through=False) r2 = nw.from_native(df, eager_only=False, pass_through=True) diff --git a/tests/translate/get_native_namespace_test.py b/tests/translate/get_native_namespace_test.py index 5a15069ed2..0443d86594 100644 --- a/tests/translate/get_native_namespace_test.py +++ b/tests/translate/get_native_namespace_test.py @@ -62,25 +62,25 @@ def _get_expected_namespace(constructor_name: str) -> Any | None: # noqa: PLR09 return None # pragma: no cover -def test_native_namespace_frame(constructor: Constructor) -> None: - constructor_name = str(constructor) +def test_native_namespace_frame(nw_frame_constructor: Constructor) -> None: + constructor_name = str(nw_frame_constructor) if "pyspark" in constructor_name and "sqlframe" not in constructor_name: pytest.skip(reason="Requires special handling for spark local vs spark connect") expected_namespace = _get_expected_namespace(constructor_name=constructor_name) - df = nw.from_native(constructor(data)) + df = nw.from_native(nw_frame_constructor(data)) assert nw.get_native_namespace(df) is expected_namespace assert nw.get_native_namespace(df.to_native()) is expected_namespace assert nw.get_native_namespace(df.lazy().to_native()) is expected_namespace -def test_native_namespace_series(constructor_eager: ConstructorEager) -> None: - constructor_name = str(constructor_eager) +def test_native_namespace_series(nw_eager_constructor: ConstructorEager) -> None: + constructor_name = str(nw_eager_constructor) expected_namespace = _get_expected_namespace(constructor_name=constructor_name) - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert nw.get_native_namespace(df["a"].to_native()) is expected_namespace assert nw.get_native_namespace(df, df["a"].to_native()) is expected_namespace diff --git a/tests/translate/to_native_test.py b/tests/translate/to_native_test.py index f84cf80dd6..1ea9d7014c 100644 --- a/tests/translate/to_native_test.py +++ b/tests/translate/to_native_test.py @@ -25,11 +25,15 @@ ], ) def test_to_native( - constructor_eager: ConstructorEager, method: str, *, pass_through: bool, context: Any + nw_eager_constructor: ConstructorEager, + method: str, + *, + pass_through: bool, + context: Any, ) -> None: if method == "to_numpy": pytest.importorskip("numpy") - df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) + df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) with context: nw.to_native(getattr(df, method)(), pass_through=pass_through) diff --git a/tests/utils.py b/tests/utils.py index c51ee91d00..a661aecbf7 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -61,7 +61,7 @@ def get_module_version_as_tuple(module_name: str) -> tuple[int, ...]: ) ID_CUDF = frozenset(("cudf",)) _CONSTRUCTOR_FIXTURE_NAMES = frozenset[str]( - ("constructor_eager", "constructor", "constructor_pandas_like") + ("nw_eager_constructor", "nw_frame_constructor", "nw_pandas_like_constructor") ) @@ -200,9 +200,13 @@ def windows_has_tzdata() -> bool: # pragma: no cover return (Path.home() / "Downloads" / "tzdata").exists() -def is_pyarrow_windows_no_tzdata(constructor: Constructor, /) -> bool: +def is_pyarrow_windows_no_tzdata(nw_frame_constructor: Constructor, /) -> bool: """Skip test on Windows when the tz database is not configured.""" - return "pyarrow" in str(constructor) and is_windows() and not windows_has_tzdata() + return ( + "pyarrow" in str(nw_frame_constructor) + and is_windows() + and not windows_has_tzdata() + ) def uses_pyarrow_backend(constructor: Constructor | ConstructorEager) -> bool: @@ -237,9 +241,9 @@ def time_unit_compat(time_unit: TimeUnit, request: pytest.FixtureRequest, /) -> return time_unit -def is_pyspark_connect(constructor: Constructor) -> bool: +def is_pyspark_connect(nw_frame_constructor: Constructor) -> bool: is_spark_connect = bool(os.environ.get("SPARK_CONNECT", None)) - return is_spark_connect and ("pyspark" in str(constructor)) + return is_spark_connect and ("pyspark" in str(nw_frame_constructor)) def xfail_if_pyspark_connect( # pragma: no cover diff --git a/tests/v1_test.py b/tests/v1_test.py index 9882c4ed15..9f8838b7f7 100644 --- a/tests/v1_test.py +++ b/tests/v1_test.py @@ -309,16 +309,16 @@ def test_enum_v1_is_enum_unstable() -> None: def test_cast_to_enum_v1( - request: pytest.FixtureRequest, constructor: Constructor + request: pytest.FixtureRequest, nw_frame_constructor: Constructor ) -> None: # Backends that do not (yet) support Enum dtype if any( - backend in str(constructor) + backend in str(nw_frame_constructor) for backend in ("pyarrow_table", "sqlframe", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - df_native = constructor({"a": ["a", "b"]}) + df_native = nw_frame_constructor({"a": ["a", "b"]}) msg = re.escape("Converting to Enum is not supported in narwhals.stable.v1") with pytest.raises(NotImplementedError, match=msg): @@ -454,17 +454,17 @@ def test_all_horizontal() -> None: assert_equal_data(result, expected) -def test_with_row_index(constructor: Constructor) -> None: - if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): +def test_with_row_index(nw_frame_constructor: Constructor) -> None: + if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"abc": ["foo", "bars"], "xyz": [100, 200], "const": [42, 42]} - frame = nw_v1.from_native(constructor(data)) + frame = nw_v1.from_native(nw_frame_constructor(data)) msg = "Cannot pass `order_by`" context = ( pytest.raises(TypeError, match=msg) - if any(x in str(constructor) for x in ("duckdb", "pyspark")) + if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark")) else does_not_raise() ) @@ -866,9 +866,9 @@ def func( func(pl.DataFrame(data), pd.Series(data["a"])) -def test_expr_sample(constructor_eager: ConstructorEager) -> None: +def test_expr_sample(nw_eager_constructor: ConstructorEager) -> None: df = nw_v1.from_native( - constructor_eager({"a": [1, 2, 3], "b": [4, 5, 6]}), eager_only=True + nw_eager_constructor({"a": [1, 2, 3], "b": [4, 5, 6]}), eager_only=True ) result_expr = df.select(nw_v1.col("a").sample(n=2)).shape @@ -886,17 +886,19 @@ def test_is_frame() -> None: assert nw_v1.dependencies.is_narwhals_dataframe(lf.collect()) -def test_with_version(constructor: Constructor) -> None: - lf = nw_v1.from_native(constructor({"a": [1, 2]})).lazy() +def test_with_version(nw_frame_constructor: Constructor) -> None: + lf = nw_v1.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() assert isinstance(lf, nw_v1.LazyFrame) assert lf._compliant_frame._with_version(Version.MAIN)._version is Version.MAIN @pytest.mark.parametrize("n", [1, 2]) @pytest.mark.parametrize("offset", [1, 2]) -def test_gather_every(constructor_eager: ConstructorEager, n: int, offset: int) -> None: +def test_gather_every( + nw_eager_constructor: ConstructorEager, n: int, offset: int +) -> None: data = {"a": list(range(10))} - df_v1 = nw_v1.from_native(constructor_eager(data)) + df_v1 = nw_v1.from_native(nw_eager_constructor(data)) result = df_v1.gather_every(n=n, offset=offset) expected = {"a": data["a"][offset::n]} assert_equal_data(result, expected) @@ -1154,26 +1156,26 @@ def test_series_from_iterable( assert_equal_series(result, expected, name) -def test_mode_single_expr(constructor_eager: ConstructorEager) -> None: +def test_mode_single_expr(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - df = nw_v1.from_native(constructor_eager(data)) + df = nw_v1.from_native(nw_eager_constructor(data)) result = df.select(nw_v1.col("a").mode()).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series(constructor_eager: ConstructorEager) -> None: +def test_mode_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - series = nw_v1.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw_v1.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.mode().sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_different_lengths(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw_v1.from_native(constructor_eager({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw_v1.from_native(nw_eager_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) with pytest.raises(ShapeError): df.select(nw_v1.col("a", "b").mode()) @@ -1186,8 +1188,10 @@ def test_dtype___slots__(dtype: DType) -> None: dtype.i_also_dont_exist = 528329 # type: ignore[attr-defined] -def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "dask" in str(constructor): +def test_any_value_expr( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "dask" in str(nw_frame_constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -1196,15 +1200,15 @@ def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest "b": [1, 2, 3, 4, 5, 6], "c": [None, None, 1, None, 2, None], } - df = nw_v1.from_native(constructor(data)) + df = nw_v1.from_native(nw_frame_constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df.select(nw_v1.col("a", "b").any_value()) -def test_any_value_series(constructor_eager: ConstructorEager) -> None: +def test_any_value_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 1, 2, 2, 3]} - df = nw_v1.from_native(constructor_eager(data)) + df = nw_v1.from_native(nw_eager_constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df["a"].any_value() diff --git a/tests/v2_test.py b/tests/v2_test.py index 7a1903425c..e819eb4d04 100644 --- a/tests/v2_test.py +++ b/tests/v2_test.py @@ -346,8 +346,8 @@ def fun2(self, df: Any) -> Any: # pragma: no cover Foo().func() -def test_with_version(constructor: Constructor) -> None: - lf = nw_v2.from_native(constructor({"a": [1, 2]})).lazy() +def test_with_version(nw_frame_constructor: Constructor) -> None: + lf = nw_v2.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() assert isinstance(lf, nw_v2.LazyFrame) assert lf._compliant_frame._with_version(Version.MAIN)._version is Version.MAIN @@ -501,32 +501,34 @@ def test_series_from_iterable( assert_equal_series(result, expected, name) -def test_mode_single_expr(constructor_eager: ConstructorEager) -> None: +def test_mode_single_expr(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - df = nw_v2.from_native(constructor_eager(data)) + df = nw_v2.from_native(nw_eager_constructor(data)) result = df.select(nw_v2.col("a").mode()).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series(constructor_eager: ConstructorEager) -> None: +def test_mode_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - series = nw_v2.from_native(constructor_eager(data), eager_only=True)["a"] + series = nw_v2.from_native(nw_eager_constructor(data), eager_only=True)["a"] result = series.mode().sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_different_lengths(constructor_eager: ConstructorEager) -> None: - if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths(nw_eager_constructor: ConstructorEager) -> None: + if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw_v2.from_native(constructor_eager({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw_v2.from_native(nw_eager_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) with pytest.raises(ShapeError): df.select(nw_v2.col("a", "b").mode()) -def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "dask" in str(constructor): +def test_any_value_expr( + nw_frame_constructor: Constructor, request: pytest.FixtureRequest +) -> None: + if "dask" in str(nw_frame_constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -535,15 +537,15 @@ def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest "b": [1, 2, 3, 4, 5, 6], "c": [None, None, 1, None, 2, None], } - df = nw_v2.from_native(constructor(data)) + df = nw_v2.from_native(nw_frame_constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df.select(nw_v2.col("a", "b").any_value()) -def test_any_value_series(constructor_eager: ConstructorEager) -> None: +def test_any_value_series(nw_eager_constructor: ConstructorEager) -> None: data = {"a": [1, 1, 1, 2, 2, 3]} - df = nw_v2.from_native(constructor_eager(data)) + df = nw_v2.from_native(nw_eager_constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df["a"].any_value() From fe708fbc2c3dc5ba96eeceb98d4bc603d885a82b Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sat, 18 Apr 2026 22:58:07 +0200 Subject: [PATCH 05/11] CI fix --- .github/workflows/extremes.yml | 8 ++++---- .github/workflows/pytest-ibis.yml | 2 +- .github/workflows/pytest-modin.yml | 2 +- .github/workflows/pytest-pyspark.yml | 6 +++--- .github/workflows/pytest.yml | 16 ++++++++-------- .github/workflows/random_ci_pytest.yml | 2 +- 6 files changed, 18 insertions(+), 18 deletions(-) diff --git a/.github/workflows/extremes.yml b/.github/workflows/extremes.yml index f18ee5a697..8d5d4a007b 100644 --- a/.github/workflows/extremes.yml +++ b/.github/workflows/extremes.yml @@ -46,7 +46,7 @@ jobs: echo "$DEPS" | grep 'duckdb==1.1' - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pyarrow,polars[eager],polars[lazy],duckdb + coverage run -m pytest tests --runslow --nw-backends=pandas,pyarrow,polars[eager],polars[lazy],duckdb coverage combine coverage report --fail-under=50 @@ -87,7 +87,7 @@ jobs: echo "$DEPS" | grep 'duckdb==1.2' - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pyarrow,polars[eager],polars[lazy],duckdb + coverage run -m pytest tests --runslow --nw-backends=pandas,pyarrow,polars[eager],polars[lazy],duckdb coverage combine coverage report --fail-under=50 @@ -127,7 +127,7 @@ jobs: echo "$DEPS" | grep 'duckdb==1.3' - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pyarrow,polars[eager],polars[lazy],dask,duckdb + coverage run -m pytest tests --runslow --nw-backends=pandas,pyarrow,polars[eager],polars[lazy],dask,duckdb coverage combine coverage report --fail-under=50 @@ -185,6 +185,6 @@ jobs: echo "$DEPS" | grep 'dask.*@' - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb + coverage run -m pytest tests --runslow --nw-backends=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb coverage combine coverage report --fail-under=50 diff --git a/.github/workflows/pytest-ibis.yml b/.github/workflows/pytest-ibis.yml index 5672b5aa06..9823bf1985 100644 --- a/.github/workflows/pytest-ibis.yml +++ b/.github/workflows/pytest-ibis.yml @@ -37,4 +37,4 @@ jobs: - name: show-deps run: uv pip freeze - name: Run pytest - run: pytest tests --constructors ibis + run: pytest tests --nw-backends ibis diff --git a/.github/workflows/pytest-modin.yml b/.github/workflows/pytest-modin.yml index 2a09e2bd2c..3f491f4ea4 100644 --- a/.github/workflows/pytest-modin.yml +++ b/.github/workflows/pytest-modin.yml @@ -35,4 +35,4 @@ jobs: - name: show-deps run: uv pip freeze - name: Run pytest - run: pytest tests --constructors modin[pyarrow] + run: pytest tests --nw-backends modin[pyarrow] diff --git a/.github/workflows/pytest-pyspark.yml b/.github/workflows/pytest-pyspark.yml index 125310e5cf..8ec17c834a 100644 --- a/.github/workflows/pytest-pyspark.yml +++ b/.github/workflows/pytest-pyspark.yml @@ -42,7 +42,7 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors pyspark + coverage run -m pytest tests --runslow --nw-backends pyspark coverage combine coverage report --fail-under=95 --include "narwhals/_spark_like/*" @@ -71,7 +71,7 @@ jobs: - name: show-deps run: uv pip freeze - name: Run pytest - run: pytest tests --constructors pyspark + run: pytest tests --nw-backends pyspark pytest-pyspark-connect-constructor: strategy: @@ -138,7 +138,7 @@ jobs: - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors "pyspark[connect]" + coverage run -m pytest tests --runslow --nw-backends "pyspark[connect]" coverage combine coverage report --fail-under=95 --include="narwhals/_spark_like/*" diff --git a/.github/workflows/pytest.yml b/.github/workflows/pytest.yml index a908544fee..23d6aa9548 100644 --- a/.github/workflows/pytest.yml +++ b/.github/workflows/pytest.yml @@ -37,7 +37,7 @@ jobs: COVERAGE_PATCH_EXECV: ${{ matrix.os == 'windows-latest' && 'subprocess' || 'execv' }} COVERAGE_PATCH_FORK: ${{ matrix.os == 'windows-latest' && 'subprocess' || 'fork' }} run: | - coverage run -m pytest tests --constructors=pandas,pyarrow,polars[eager],polars[lazy] + coverage run -m pytest tests --nw-backends=pandas,pyarrow,polars[eager],polars[lazy] coverage combine coverage report --fail-under=75 - name: install-test-plugin @@ -74,7 +74,7 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],duckdb,sqlframe --durations=30 + coverage run -m pytest tests --runslow --nw-backends=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],duckdb,sqlframe --durations=30 coverage combine coverage report --fail-under=95 @@ -108,7 +108,7 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb,sqlframe --durations=30 + coverage run -m pytest tests --runslow --nw-backends=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb,sqlframe --durations=30 coverage combine coverage report --fail-under=100 - name: Run doctests @@ -139,20 +139,20 @@ jobs: uv pip install -e ".[pandas]" --group tests uv pip freeze - name: Run pytest (pandas and pandas[nullable]) - run: pytest tests --runslow --constructors=pandas,pandas[nullable] + run: pytest tests --runslow --nw-backends=pandas,pandas[nullable] - name: install-more-reqs run: | uv pip install -U pyarrow uv pip freeze - name: Run pytest (pandas[pyarrow] and pyarrow) - run: pytest tests --runslow --constructors=pandas[pyarrow],pyarrow + run: pytest tests --runslow --nw-backends=pandas[pyarrow],pyarrow - name: install-polars run: | uv pip uninstall pandas pyarrow uv pip install polars uv pip freeze - name: Run pytest (polars) - run: pytest tests --runslow --constructors=polars[eager],polars[lazy] + run: pytest tests --runslow --nw-backends=polars[eager],polars[lazy] python-314: strategy: @@ -177,7 +177,7 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --runslow --constructors=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb,sqlframe --durations=30 + coverage run -m pytest tests --runslow --nw-backends=pandas,pandas[nullable],pandas[pyarrow],pyarrow,polars[eager],polars[lazy],dask,duckdb,sqlframe --durations=30 coverage combine coverage report --fail-under=50 @@ -206,6 +206,6 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --runslow --durations=30 --constructors=pandas,pandas[nullable],pandas[pyarrow],pyarrow + coverage run -m pytest tests --runslow --durations=30 --nw-backends=pandas,pandas[nullable],pandas[pyarrow],pyarrow coverage combine coverage report --fail-under=50 diff --git a/.github/workflows/random_ci_pytest.yml b/.github/workflows/random_ci_pytest.yml index 8531c0e639..7e73be44ab 100644 --- a/.github/workflows/random_ci_pytest.yml +++ b/.github/workflows/random_ci_pytest.yml @@ -37,6 +37,6 @@ jobs: run: uv pip freeze - name: Run pytest run: | - coverage run -m pytest tests --constructors=pandas,pyarrow,polars[eager],polars[lazy] + coverage run -m pytest tests --nw-backends=pandas,pyarrow,polars[eager],polars[lazy] coverage combine coverage report --fail-under=75 From 474f5e483c8de16e4c8c918c39dc2ab191d4d510 Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sun, 19 Apr 2026 10:02:40 +0200 Subject: [PATCH 06/11] revert test changes --- tests/conftest.py | 24 +++ .../is_narwhals_dataframe_test.py | 4 +- .../is_narwhals_lazyframe_test.py | 4 +- tests/dependencies/is_narwhals_series_test.py | 4 +- tests/dtypes/dtypes_test.py | 24 ++- tests/expr_and_series/abs_test.py | 8 +- tests/expr_and_series/all_horizontal_test.py | 48 +++-- tests/expr_and_series/any_all_test.py | 8 +- tests/expr_and_series/any_horizontal_test.py | 32 ++- tests/expr_and_series/any_value_test.py | 39 ++-- tests/expr_and_series/arithmetic_test.py | 72 ++++--- tests/expr_and_series/binary_test.py | 6 +- tests/expr_and_series/cast_test.py | 113 +++++------ .../cat/get_categories_test.py | 16 +- tests/expr_and_series/clip_test.py | 23 +-- tests/expr_and_series/coalesce_test.py | 22 +-- tests/expr_and_series/concat_str_test.py | 10 +- tests/expr_and_series/corr_test.py | 28 ++- tests/expr_and_series/cos_test.py | 8 +- tests/expr_and_series/count_test.py | 8 +- tests/expr_and_series/cum_count_test.py | 24 +-- tests/expr_and_series/cum_max_test.py | 73 ++++--- tests/expr_and_series/cum_min_test.py | 81 ++++---- tests/expr_and_series/cum_prod_test.py | 33 ++-- tests/expr_and_series/cum_sum_test.py | 72 ++++--- tests/expr_and_series/diff_test.py | 26 +-- .../expr_and_series/division_by_zero_test.py | 54 +++-- tests/expr_and_series/double_selected_test.py | 4 +- tests/expr_and_series/double_test.py | 8 +- tests/expr_and_series/drop_nulls_test.py | 16 +- .../dt/convert_time_zone_test.py | 52 ++--- .../dt/datetime_attributes_test.py | 48 ++--- .../dt/datetime_duration_test.py | 32 +-- tests/expr_and_series/dt/offset_by_test.py | 81 ++++---- .../dt/replace_time_zone_test.py | 44 ++--- tests/expr_and_series/dt/timestamp_test.py | 64 +++--- tests/expr_and_series/dt/to_string_test.py | 34 ++-- tests/expr_and_series/dt/truncate_test.py | 46 ++--- tests/expr_and_series/ewm_test.py | 30 +-- tests/expr_and_series/exclude_test.py | 4 +- tests/expr_and_series/exp_test.py | 8 +- tests/expr_and_series/fill_nan_test.py | 24 ++- tests/expr_and_series/fill_null_test.py | 116 +++++------ tests/expr_and_series/filter_test.py | 26 +-- tests/expr_and_series/first_last_test.py | 80 ++++---- tests/expr_and_series/floor_ceil_test.py | 16 +- tests/expr_and_series/format_test.py | 4 +- .../horizontal_broadcasts_test.py | 6 +- tests/expr_and_series/is_between_test.py | 24 +-- tests/expr_and_series/is_close_test.py | 60 +++--- tests/expr_and_series/is_duplicated_test.py | 16 +- tests/expr_and_series/is_finite_test.py | 37 ++-- .../expr_and_series/is_first_distinct_test.py | 37 ++-- tests/expr_and_series/is_in_test.py | 20 +- .../expr_and_series/is_last_distinct_test.py | 48 ++--- tests/expr_and_series/is_nan_test.py | 36 ++-- tests/expr_and_series/is_null_test.py | 8 +- tests/expr_and_series/is_unique_test.py | 27 ++- tests/expr_and_series/kurtosis_test.py | 14 +- tests/expr_and_series/len_test.py | 18 +- tests/expr_and_series/list/contains_test.py | 14 +- tests/expr_and_series/list/get_test.py | 49 +++-- tests/expr_and_series/list/len_test.py | 18 +- tests/expr_and_series/list/max_test.py | 18 +- tests/expr_and_series/list/mean_test.py | 18 +- tests/expr_and_series/list/median_test.py | 32 ++- tests/expr_and_series/list/min_test.py | 18 +- tests/expr_and_series/list/sort_test.py | 22 +-- tests/expr_and_series/list/sum_test.py | 20 +- tests/expr_and_series/list/unique_test.py | 16 +- tests/expr_and_series/lit_test.py | 54 +++-- tests/expr_and_series/log_test.py | 8 +- tests/expr_and_series/map_batches_test.py | 26 +-- tests/expr_and_series/max_horizontal_test.py | 8 +- tests/expr_and_series/max_test.py | 8 +- tests/expr_and_series/mean_horizontal_test.py | 14 +- tests/expr_and_series/mean_test.py | 8 +- tests/expr_and_series/median_test.py | 24 +-- tests/expr_and_series/min_horizontal_test.py | 8 +- tests/expr_and_series/min_test.py | 8 +- tests/expr_and_series/mode_test.py | 38 ++-- tests/expr_and_series/n_unique_test.py | 26 ++- tests/expr_and_series/name/keep_test.py | 12 +- tests/expr_and_series/name/map_test.py | 14 +- tests/expr_and_series/name/prefix_test.py | 14 +- tests/expr_and_series/name/suffix_test.py | 14 +- .../expr_and_series/name/to_lowercase_test.py | 14 +- .../expr_and_series/name/to_uppercase_test.py | 14 +- tests/expr_and_series/nth_test.py | 8 +- tests/expr_and_series/null_count_test.py | 8 +- tests/expr_and_series/operators_test.py | 42 ++-- .../order_dependent_lazy_test.py | 4 +- tests/expr_and_series/over_pushdown_test.py | 6 +- tests/expr_and_series/over_test.py | 174 ++++++++-------- tests/expr_and_series/pipe_test.py | 8 +- tests/expr_and_series/quantile_test.py | 18 +- tests/expr_and_series/rank_test.py | 110 +++++------ tests/expr_and_series/reduction_test.py | 26 +-- tests/expr_and_series/replace_strict_test.py | 97 +++++---- tests/expr_and_series/rolling_mean_test.py | 32 +-- tests/expr_and_series/rolling_std_test.py | 38 ++-- tests/expr_and_series/rolling_sum_test.py | 40 ++-- tests/expr_and_series/rolling_var_test.py | 38 ++-- tests/expr_and_series/round_test.py | 8 +- tests/expr_and_series/sample_test.py | 8 +- tests/expr_and_series/shift_test.py | 30 +-- tests/expr_and_series/sin_test.py | 8 +- tests/expr_and_series/skew_test.py | 20 +- tests/expr_and_series/sqrt_test.py | 8 +- tests/expr_and_series/std_test.py | 10 +- tests/expr_and_series/str/contains_test.py | 40 ++-- tests/expr_and_series/str/head_test.py | 8 +- tests/expr_and_series/str/len_chars_test.py | 8 +- tests/expr_and_series/str/pad_test.py | 32 +-- tests/expr_and_series/str/replace_test.py | 92 ++++----- tests/expr_and_series/str/slice_test.py | 8 +- tests/expr_and_series/str/split_test.py | 23 ++- .../str/starts_with_ends_with_test.py | 16 +- tests/expr_and_series/str/strip_chars_test.py | 10 +- tests/expr_and_series/str/tail_test.py | 8 +- tests/expr_and_series/str/to_date_test.py | 48 ++--- tests/expr_and_series/str/to_datetime_test.py | 65 +++--- .../expr_and_series/str/to_titlecase_test.py | 12 +- .../str/to_uppercase_to_lowercase_test.py | 20 +- tests/expr_and_series/str/zfill_test.py | 22 +-- tests/expr_and_series/struct_/field_test.py | 22 +-- tests/expr_and_series/struct_test.py | 70 +++---- tests/expr_and_series/sum_horizontal_test.py | 22 +-- tests/expr_and_series/sum_test.py | 8 +- tests/expr_and_series/unary_test.py | 42 ++-- tests/expr_and_series/unique_test.py | 22 +-- tests/expr_and_series/var_test.py | 10 +- tests/expr_and_series/when_test.py | 184 ++++++++--------- tests/expression_parsing_test.py | 24 ++- tests/frame/add_test.py | 6 +- tests/frame/array_dunder_test.py | 22 +-- tests/frame/clone_test.py | 4 +- tests/frame/collect_test.py | 48 ++--- tests/frame/columns_test.py | 8 +- tests/frame/concat_test.py | 35 ++-- tests/frame/double_test.py | 4 +- tests/frame/drop_nulls_test.py | 8 +- tests/frame/drop_test.py | 18 +- tests/frame/eq_test.py | 6 +- tests/frame/estimated_size_test.py | 4 +- tests/frame/explode_test.py | 38 ++-- tests/frame/filter_test.py | 66 +++---- tests/frame/from_dict_test.py | 18 +- tests/frame/get_column_test.py | 4 +- tests/frame/getitem_test.py | 128 ++++++------ tests/frame/group_by_test.py | 187 ++++++++---------- tests/frame/head_test.py | 4 +- tests/frame/invalid_test.py | 4 +- tests/frame/is_duplicated_test.py | 8 +- tests/frame/is_empty_test.py | 4 +- tests/frame/is_unique_test.py | 8 +- tests/frame/item_test.py | 8 +- tests/frame/join_test.py | 183 ++++++++--------- tests/frame/lazy_test.py | 30 +-- tests/frame/len_test.py | 4 +- tests/frame/null_count_test.py | 4 +- tests/frame/pipe_test.py | 4 +- tests/frame/pivot_test.py | 44 ++--- tests/frame/rename_test.py | 4 +- tests/frame/row_test.py | 6 +- tests/frame/rows_test.py | 26 +-- tests/frame/sample_test.py | 14 +- tests/frame/schema_test.py | 26 +-- tests/frame/select_test.py | 44 ++--- tests/frame/shape_test.py | 4 +- tests/frame/sink_parquet_test.py | 8 +- tests/frame/sort_test.py | 8 +- tests/frame/tail_test.py | 4 +- tests/frame/to_arrow_test.py | 4 +- tests/frame/to_dict_test.py | 8 +- tests/frame/to_native_test.py | 4 +- tests/frame/to_numpy_test.py | 12 +- tests/frame/to_pandas_test.py | 10 +- tests/frame/to_polars_test.py | 4 +- tests/frame/top_k_test.py | 20 +- tests/frame/unique_test.py | 52 ++--- tests/frame/unpivot_test.py | 24 +-- tests/frame/with_columns_sequence_test.py | 4 +- tests/frame/with_columns_test.py | 48 +++-- tests/frame/with_row_index_test.py | 35 ++-- tests/frame/write_csv_test.py | 10 +- tests/frame/write_parquet_test.py | 4 +- tests/from_dict_test.py | 18 +- tests/from_numpy_test.py | 20 +- tests/joblib_test.py | 10 +- tests/modern_polars/ewm_mean_test.py | 8 +- tests/modern_polars/filter_test.py | 4 +- tests/modern_polars/method_chaining_2_test.py | 4 +- tests/modern_polars/method_chaining_test.py | 16 +- tests/modern_polars/performance_test.py | 8 +- tests/modern_polars/pivot_test.py | 8 +- tests/modern_polars/unpivot_test.py | 4 +- tests/namespace_test.py | 4 +- tests/new_series_test.py | 4 +- ...erve_pandas_like_columns_name_attr_test.py | 10 +- tests/read_scan_test.py | 18 +- tests/selectors_test.py | 92 ++++----- tests/series_only/__contains___test.py | 12 +- tests/series_only/__iter___test.py | 6 +- tests/series_only/alias_rename_test.py | 4 +- tests/series_only/arg_max_test.py | 8 +- tests/series_only/arg_min_test.py | 8 +- tests/series_only/arg_true_test.py | 4 +- tests/series_only/array_dunder_test.py | 20 +- tests/series_only/cast_test.py | 12 +- tests/series_only/gather_every_test.py | 4 +- tests/series_only/getitem_test.py | 26 +-- tests/series_only/head_test.py | 4 +- tests/series_only/hist_test.py | 42 ++-- tests/series_only/is_empty_test.py | 4 +- .../is_ordered_categorical_test.py | 4 +- tests/series_only/is_sorted_test.py | 10 +- tests/series_only/item_test.py | 8 +- tests/series_only/scatter_test.py | 8 +- tests/series_only/shape_test.py | 6 +- tests/series_only/sort_test.py | 11 +- tests/series_only/tail_test.py | 4 +- tests/series_only/to_arrow_test.py | 12 +- tests/series_only/to_dummy_test.py | 24 +-- tests/series_only/to_frame_test.py | 4 +- tests/series_only/to_list_test.py | 4 +- tests/series_only/to_native_test.py | 6 +- tests/series_only/to_numpy_test.py | 18 +- tests/series_only/to_pandas_test.py | 8 +- tests/series_only/to_polars_test.py | 4 +- tests/series_only/value_counts_test.py | 8 +- tests/series_only/zip_with_test.py | 20 +- tests/testing/assert_frame_equal_test.py | 56 +++--- tests/testing/assert_series_equal_test.py | 64 +++--- tests/testing/plugin_test.py | 2 +- tests/translate/from_native_test.py | 17 +- tests/translate/get_native_namespace_test.py | 12 +- tests/translate/to_native_test.py | 8 +- tests/utils.py | 14 +- tests/v1_test.py | 54 +++-- tests/v2_test.py | 30 ++- 241 files changed, 2883 insertions(+), 3253 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index dbfef9e335..ff79ea62f6 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -19,6 +19,7 @@ from typing_extensions import TypeAlias from narwhals._typing import EagerAllowed + from narwhals.testing.typing import EagerFrameConstructor, FrameConstructor from narwhals.typing import NonNestedDType from tests.utils import NestedOrEnumDType @@ -117,3 +118,26 @@ def non_nested_type(request: pytest.FixtureRequest) -> type[NonNestedDType]: def nested_dtype(request: pytest.FixtureRequest) -> NestedOrEnumDType: dtype: NestedOrEnumDType = request.param return dtype + + +@pytest.fixture +def constructor(nw_frame_constructor: FrameConstructor) -> FrameConstructor: + # Alias fixture for backward compatibility + # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly + return nw_frame_constructor + + +@pytest.fixture +def constructor_eager(nw_eager_constructor: EagerFrameConstructor) -> FrameConstructor: + # Alias fixture for backward compatibility + # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly + return nw_eager_constructor + + +@pytest.fixture +def constructor_pandas_like( + nw_pandas_like_constructor: EagerFrameConstructor, +) -> FrameConstructor: + # Alias fixture for backward compatibility + # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly + return nw_pandas_like_constructor diff --git a/tests/dependencies/is_narwhals_dataframe_test.py b/tests/dependencies/is_narwhals_dataframe_test.py index 4880a254d0..aeedf15981 100644 --- a/tests/dependencies/is_narwhals_dataframe_test.py +++ b/tests/dependencies/is_narwhals_dataframe_test.py @@ -9,8 +9,8 @@ from tests.utils import ConstructorEager -def test_is_narwhals_dataframe(nw_eager_constructor: ConstructorEager) -> None: - df = nw_eager_constructor({"col1": [1, 2], "col2": [3, 4]}) +def test_is_narwhals_dataframe(constructor_eager: ConstructorEager) -> None: + df = constructor_eager({"col1": [1, 2], "col2": [3, 4]}) assert is_narwhals_dataframe(nw.from_native(df)) assert not is_narwhals_dataframe(df) diff --git a/tests/dependencies/is_narwhals_lazyframe_test.py b/tests/dependencies/is_narwhals_lazyframe_test.py index 96be4bc4cf..0e4c6e1bd9 100644 --- a/tests/dependencies/is_narwhals_lazyframe_test.py +++ b/tests/dependencies/is_narwhals_lazyframe_test.py @@ -10,8 +10,8 @@ from tests.utils import Constructor -def test_is_narwhals_lazyframe(nw_frame_constructor: Constructor) -> None: - lf = nw_frame_constructor({"a": [1, 2, 3]}) +def test_is_narwhals_lazyframe(constructor: Constructor) -> None: + lf = constructor({"a": [1, 2, 3]}) assert is_narwhals_lazyframe(nw.from_native(lf).lazy()) assert not is_narwhals_lazyframe(lf) diff --git a/tests/dependencies/is_narwhals_series_test.py b/tests/dependencies/is_narwhals_series_test.py index b3b01bb848..659696d108 100644 --- a/tests/dependencies/is_narwhals_series_test.py +++ b/tests/dependencies/is_narwhals_series_test.py @@ -9,8 +9,8 @@ from tests.utils import ConstructorEager -def test_is_narwhals_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw_eager_constructor({"col1": [1, 2], "col2": [3, 4]}) +def test_is_narwhals_series(constructor_eager: ConstructorEager) -> None: + df = constructor_eager({"col1": [1, 2], "col2": [3, 4]}) assert is_narwhals_series(nw.from_native(df, eager_only=True)["col1"]) assert not is_narwhals_series(nw.from_native(df, eager_only=True)["col1"].to_native()) diff --git a/tests/dtypes/dtypes_test.py b/tests/dtypes/dtypes_test.py index 3d8a0c658d..a233f955f3 100644 --- a/tests/dtypes/dtypes_test.py +++ b/tests/dtypes/dtypes_test.py @@ -146,23 +146,21 @@ def test_struct_hashes() -> None: assert len({hash(tp) for tp in (dtypes)}) == 3 -def test_2d_array( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: +def test_2d_array(constructor: Constructor, request: pytest.FixtureRequest) -> None: version_conditions = [ (PANDAS_VERSION < (2, 2), "Requires pandas 2.2+ for 2D array support"), ( - "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,), + "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,), "PyArrow 14+ required for 2D array support", ), ] for condition, reason in version_conditions: if condition: pytest.skip(reason) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): pytest.importorskip("pyarrow") - if any(x in str(nw_frame_constructor) for x in ("dask", "cudf", "pyspark")): + if any(x in str(constructor) for x in ("dask", "cudf", "pyspark")): request.applymarker( pytest.mark.xfail( reason="2D array operations not supported in these backends" @@ -170,7 +168,7 @@ def test_2d_array( ) data = {"a": [[[1, 2], [3, 4], [5, 6]]]} - df = nw.from_native(nw_frame_constructor(data)).with_columns( + df = nw.from_native(constructor(data)).with_columns( a=nw.col("a").cast(nw.Array(nw.Int64(), (3, 2))) ) assert df.collect_schema()["a"] == nw.Array(nw.Int64(), (3, 2)) @@ -415,19 +413,19 @@ def test_huge_int_to_native() -> None: ) def test_cast_decimal_to_native( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, precision: int | None, scale: int, ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): request.applymarker(pytest.mark.xfail(reason="Unsupported dtype")) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip(reason="too old to convert to decimal") data = {"a": [1.1, 2.2, 3.3]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) if df.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) @@ -619,13 +617,13 @@ def test_dtype_base_type_nested(nested_dtype: NestedOrEnumDType) -> None: ], ) def test_pandas_datetime_ignored_time_unit_warns( - nw_pandas_like_constructor: ConstructorPandasLike, + constructor_pandas_like: ConstructorPandasLike, dtype: nw.Datetime | type[nw.Datetime], context: AbstractContextManager[Any], ) -> None: data = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} expr = nw.col("a").cast(dtype) - df = nw.from_native(nw_pandas_like_constructor(data)) + df = nw.from_native(constructor_pandas_like(data)) ctx = does_not_warn() if PANDAS_VERSION >= (2,) else context with ctx: df.select(expr) diff --git a/tests/expr_and_series/abs_test.py b/tests/expr_and_series/abs_test.py index 99d2dcb186..547ff9d8dc 100644 --- a/tests/expr_and_series/abs_test.py +++ b/tests/expr_and_series/abs_test.py @@ -4,15 +4,15 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_abs(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, -4, 5]})) +def test_abs(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, -4, 5]})) result = df.select(b=nw.col("a").abs()) expected = {"b": [1, 2, 3, 4, 5]} assert_equal_data(result, expected) -def test_abs_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, -4, 5]}), eager_only=True) +def test_abs_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [1, 2, 3, -4, 5]}), eager_only=True) result = {"b": df["a"].abs()} expected = {"b": [1, 2, 3, 4, 5]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/all_horizontal_test.py b/tests/expr_and_series/all_horizontal_test.py index 50accfe523..d980b3def3 100644 --- a/tests/expr_and_series/all_horizontal_test.py +++ b/tests/expr_and_series/all_horizontal_test.py @@ -9,52 +9,50 @@ from tests.utils import POLARS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_allh(nw_frame_constructor: Constructor) -> None: +def test_allh(constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(all=nw.all_horizontal("a", nw.col("b"), ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) -def test_all_ignore_nulls(nw_frame_constructor: Constructor) -> None: - if "dask" in str(nw_frame_constructor): +def test_all_ignore_nulls(constructor: Constructor) -> None: + if "dask" in str(constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(any=nw.all_horizontal("a", "b", ignore_nulls=True)) expected = [True, True, False] assert_equal_data(result, {"any": expected}) -def test_allh_kleene( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "cudf" in str(nw_frame_constructor): +def test_allh_kleene(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() context = ( pytest.raises(ValueError, match="ignore_nulls") - if "pandas_constructor" in str(nw_frame_constructor) + if "pandas_constructor" in str(constructor) else does_not_raise() ) data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with context: result = df.select(all=nw.all_horizontal("a", "b", ignore_nulls=False)) expected = [True, None, False] assert_equal_data(result, {"all": expected}) -def test_anyh_dask(nw_frame_constructor: Constructor) -> None: - if "dask" not in str(nw_frame_constructor): +def test_anyh_dask(constructor: Constructor) -> None: + if "dask" not in str(constructor): pytest.skip() import dask.dataframe as dd import pandas as pd @@ -76,18 +74,18 @@ def test_anyh_dask(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, {"all": expected}) -def test_allh_series(nw_eager_constructor: ConstructorEager) -> None: +def test_allh_series(constructor_eager: ConstructorEager) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(all=nw.all_horizontal(df["a"], df["b"], ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) -def test_allh_all(nw_frame_constructor: Constructor) -> None: +def test_allh_all(constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(all=nw.all_horizontal(nw.all(), ignore_nulls=True)) expected = {"all": [False, False, True]} assert_equal_data(result, expected) @@ -96,11 +94,11 @@ def test_allh_all(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_allh_nth(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0): +def test_allh_nth(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 0): pytest.skip() data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.all_horizontal(nw.nth(0, 1), ignore_nulls=True)) expected = {"a": [False, False, True]} assert_equal_data(result, expected) @@ -109,13 +107,13 @@ def test_allh_nth(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_allh_iterator(nw_frame_constructor: Constructor) -> None: +def test_allh_iterator(constructor: Constructor) -> None: def iter_eq(items: Any, /) -> Any: for column, value in items: yield nw.col(column) == value data = {"a": [1, 2, 3, 3, 3], "b": ["b", "b", "a", "a", "b"]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) expr_items = [("a", 3), ("b", "b")] expected = {"a": [3], "b": ["b"]} @@ -130,9 +128,9 @@ def iter_eq(items: Any, /) -> Any: assert_equal_data(df.filter(lazy), expected) -def test_horizontal_expressions_empty(nw_frame_constructor: Constructor) -> None: +def test_horizontal_expressions_empty(constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises( ValueError, match=r"At least one expression must be passed.*all_horizontal" ): diff --git a/tests/expr_and_series/any_all_test.py b/tests/expr_and_series/any_all_test.py index 6e195f4fec..6b6cc6e35f 100644 --- a/tests/expr_and_series/any_all_test.py +++ b/tests/expr_and_series/any_all_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_any_all(nw_frame_constructor: Constructor) -> None: +def test_any_all(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [True, False, True], "b": [True, True, True], @@ -22,9 +22,9 @@ def test_any_all(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_any_all_series(nw_eager_constructor: ConstructorEager) -> None: +def test_any_all_series(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor( + constructor_eager( { "a": [True, False, True], "b": [True, True, True], diff --git a/tests/expr_and_series/any_horizontal_test.py b/tests/expr_and_series/any_horizontal_test.py index f00e679336..04f0cba76c 100644 --- a/tests/expr_and_series/any_horizontal_test.py +++ b/tests/expr_and_series/any_horizontal_test.py @@ -8,52 +8,50 @@ from tests.utils import Constructor, assert_equal_data -def test_anyh(nw_frame_constructor: Constructor) -> None: +def test_anyh(constructor: Constructor) -> None: data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(any=nw.any_horizontal(nw.col("a"), "b", ignore_nulls=True)) expected = {"any": [False, True, True]} assert_equal_data(result, expected) -def test_anyh_kleene( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "cudf" in str(nw_frame_constructor): +def test_anyh_kleene(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() context = ( pytest.raises(ValueError, match="ignore_nulls") - if "pandas_constructor" in str(nw_frame_constructor) + if "pandas_constructor" in str(constructor) else does_not_raise() ) data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with context: result = df.select(any=nw.any_horizontal("a", "b", ignore_nulls=False)) expected = [True, True, None] assert_equal_data(result, {"any": expected}) -def test_anyh_ignore_nulls(nw_frame_constructor: Constructor) -> None: - if "dask" in str(nw_frame_constructor): +def test_anyh_ignore_nulls(constructor: Constructor) -> None: + if "dask" in str(constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. # test it below separately pytest.skip() data = {"a": [True, True, False], "b": [True, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(any=nw.any_horizontal("a", "b", ignore_nulls=True)) expected = [True, True, False] assert_equal_data(result, {"any": expected}) -def test_anyh_dask(nw_frame_constructor: Constructor) -> None: - if "dask" not in str(nw_frame_constructor): +def test_anyh_dask(constructor: Constructor) -> None: + if "dask" not in str(constructor): pytest.skip() import dask.dataframe as dd import pandas as pd @@ -75,12 +73,12 @@ def test_anyh_dask(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, {"any": expected}) -def test_anyh_all(nw_frame_constructor: Constructor) -> None: - if "dask" in str(nw_frame_constructor): +def test_anyh_all(constructor: Constructor) -> None: + if "dask" in str(constructor): # Can't use `ignore_nulls` for NumPy-backed Dask, test it separately below pytest.skip() data = {"a": [False, False, True], "b": [False, True, True]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(any=nw.any_horizontal(nw.all(), ignore_nulls=False)) expected = {"any": [False, True, True]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/any_value_test.py b/tests/expr_and_series/any_value_test.py index 3ee2367989..e665fbd03c 100644 --- a/tests/expr_and_series/any_value_test.py +++ b/tests/expr_and_series/any_value_test.py @@ -19,16 +19,13 @@ @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_expr( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - *, - ignore_nulls: bool, + constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) # Aggregation result = ( @@ -36,7 +33,7 @@ def test_any_value_expr( ) assert result.shape == (1, 2) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): reason = "broadcast requires `over`, which requires DuckDB 1.3.0" pytest.skip(reason=reason) @@ -69,9 +66,9 @@ def test_any_value_expr( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_series( - nw_eager_constructor: ConstructorEager, *, ignore_nulls: bool + constructor_eager: ConstructorEager, *, ignore_nulls: bool ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = { "a": [df["a"].any_value(ignore_nulls=ignore_nulls)], @@ -87,19 +84,16 @@ def test_any_value_series( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_group_by( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - *, - ignore_nulls: bool, + constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0): reason = "too old" pytest.skip(reason) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) if ignore_nulls and df.implementation.is_pandas_like(): reason = "not implemented" @@ -124,24 +118,21 @@ def test_any_value_group_by( @pytest.mark.parametrize("ignore_nulls", [False, True]) def test_any_value_over( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - *, - ignore_nulls: bool, + constructor: Constructor, request: pytest.FixtureRequest, *, ignore_nulls: bool ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): reason = "`over` requires DuckDB 1.3.0" pytest.skip(reason=reason) - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0): reason = "too old" pytest.skip(reason) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) if ignore_nulls and df.implementation.is_pandas_like(): reason = "not implemented" diff --git a/tests/expr_and_series/arithmetic_test.py b/tests/expr_and_series/arithmetic_test.py index 1aee0bd662..af0c464e5b 100644 --- a/tests/expr_and_series/arithmetic_test.py +++ b/tests/expr_and_series/arithmetic_test.py @@ -34,18 +34,18 @@ def test_arithmetic_expr( attr: str, rhs: Any, expected: list[Any], - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(nw_frame_constructor) and attr == "__floordiv__": + if "duckdb" in str(constructor) and attr == "__floordiv__": request.applymarker(pytest.mark.xfail) if attr == "__mod__" and any( - x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 3.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a"), attr)(rhs)) assert_equal_data(result, {"a": expected}) @@ -66,17 +66,17 @@ def test_right_arithmetic_expr( attr: str, rhs: Any, expected: list[Any], - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): + if "dask" in str(constructor) and DASK_VERSION < (2024, 10): pytest.skip() if attr == "__rmod__" and any( - x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a"), attr)(rhs)) assert_equal_data(result, {"literal": expected}) @@ -98,16 +98,16 @@ def test_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(getattr(df["a"], attr)(rhs)) assert_equal_data(result, {"a": expected}) @@ -128,29 +128,29 @@ def test_right_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__rmod__" and any( - x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = getattr(df["a"], attr)(rhs) assert result_series.name == "a" assert_equal_data({"a": result_series}, {"a": expected}) def test_truediv_same_dims( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_eager_constructor): + if "polars" in str(constructor_eager): # https://github.com/pola-rs/polars/issues/17760 request.applymarker(pytest.mark.xfail) - s_left = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] - s_right = nw.from_native(nw_eager_constructor({"a": [2, 2, 1]}), eager_only=True)["a"] + s_left = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] + s_right = nw.from_native(constructor_eager({"a": [2, 2, 1]}), eager_only=True)["a"] result = s_left / s_right assert_equal_data({"a": result}, {"a": [0.5, 1.0, 3.0]}) result = s_left.__rtruediv__(s_right) @@ -160,15 +160,13 @@ def test_truediv_same_dims( @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") @pytest.mark.slow -def test_floordiv( - nw_eager_constructor: ConstructorEager, *, left: int, right: int -) -> None: - if any(x in str(nw_eager_constructor) for x in ["modin", "cudf"]): +def test_floordiv(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(constructor_eager) for x in ["modin", "cudf"]): # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left // right]} - result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( + result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( nw.col("a") // right ) assert_equal_data(result, expected) @@ -177,14 +175,14 @@ def test_floordiv( @pytest.mark.slow @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") -def test_mod(nw_eager_constructor: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin", "cudf"]): +def test_mod(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(constructor_eager) for x in ["pandas_pyarrow", "modin", "cudf"]): # pandas[pyarrow] does not implement mod # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left % right]} - result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( + result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( nw.col("a") % right ) assert_equal_data(result, expected) @@ -207,20 +205,20 @@ def test_arithmetic_expr_left_literal( attr: str, lhs: Any, expected: list[Any], - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if ("duckdb" in str(nw_frame_constructor) and attr == "__floordiv__") or ( - "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10) + if ("duckdb" in str(constructor) and attr == "__floordiv__") or ( + "dask" in str(constructor) and DASK_VERSION < (2024, 10) ): request.applymarker(pytest.mark.xfail) if attr == "__mod__" and any( - x in str(nw_frame_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 4.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(lhs, attr)(nw.col("a"))) assert_equal_data(result, {"literal": expected}) @@ -242,25 +240,25 @@ def test_arithmetic_series_left_literal( attr: str, lhs: Any, expected: list[Any], - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 4.0]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(getattr(lhs, attr)(nw.col("a"))) assert_equal_data(result, {"literal": expected}) -def test_std_broadcating(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_std_broadcating(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): # `std(ddof=2)` fails for duckdb here pytest.skip() - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor({"a": [1, 2, 3]})) result = df.with_columns(b=nw.col("a").std()).sort("a") expected = {"a": [1, 2, 3], "b": [1.0, 1.0, 1.0]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/binary_test.py b/tests/expr_and_series/binary_test.py index c64ca8e67f..6140ead120 100644 --- a/tests/expr_and_series/binary_test.py +++ b/tests/expr_and_series/binary_test.py @@ -6,11 +6,11 @@ from tests.utils import DASK_VERSION, Constructor, assert_equal_data -def test_expr_binary(nw_frame_constructor: Constructor) -> None: - if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): +def test_expr_binary(constructor: Constructor) -> None: + if "dask" in str(constructor) and DASK_VERSION < (2024, 10): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) result = nw.from_native(df_raw).with_columns( a=(1 + 3 * nw.col("a")) * (1 / nw.col("a")), b=nw.col("z") / (2 - nw.col("b")), diff --git a/tests/expr_and_series/cast_test.py b/tests/expr_and_series/cast_test.py index 581629863a..90282ea596 100644 --- a/tests/expr_and_series/cast_test.py +++ b/tests/expr_and_series/cast_test.py @@ -65,17 +65,17 @@ @pytest.mark.filterwarnings("ignore:casting period[M] values to int64:FutureWarning") -def test_cast(nw_frame_constructor: Constructor) -> None: - if "pyarrow_table_constructor" in str(nw_frame_constructor) and PYARROW_VERSION <= ( +def test_cast(constructor: Constructor) -> None: + if "pyarrow_table_constructor" in str(constructor) and PYARROW_VERSION <= ( 15, ): # pragma: no cover pytest.skip() - if "pyspark" in str(nw_frame_constructor): + if "pyspark" in str(constructor): incompatible_columns = SPARK_LIKE_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "duckdb" in str(nw_frame_constructor): + elif "duckdb" in str(constructor): incompatible_columns = DUCKDB_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "ibis" in str(nw_frame_constructor): + elif "ibis" in str(constructor): incompatible_columns = IBIS_INCOMPATIBLE_COLUMNS # pragma: no cover else: incompatible_columns = set() @@ -83,7 +83,7 @@ def test_cast(nw_frame_constructor: Constructor) -> None: data = {c: v for c, v in DATA.items() if c not in incompatible_columns} schema = {c: t for c, t in SCHEMA.items() if c not in incompatible_columns} - df = nw.from_native(nw_frame_constructor(data)).select( + df = nw.from_native(constructor(data)).select( nw.col(col_).cast(dtype) for col_, dtype in schema.items() ) @@ -112,10 +112,7 @@ def test_cast(nw_frame_constructor: Constructor) -> None: ).collect_schema() for (key, ltype), rtype in zip(result.items(), cast_map.values()): - if ( - "modin_constructor" in str(nw_frame_constructor) - and key in MODIN_XFAIL_COLUMNS - ): + if "modin_constructor" in str(constructor) and key in MODIN_XFAIL_COLUMNS: # TODO(unassigned): in modin we end up with `' None: def test_cast_series( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table_constructor" in str(nw_eager_constructor) and PYARROW_VERSION <= ( + if "pyarrow_table_constructor" in str(constructor_eager) and PYARROW_VERSION <= ( 15, ): # pragma: no cover request.applymarker(pytest.mark.xfail) df = ( - nw.from_native(nw_eager_constructor(DATA)) + nw.from_native(constructor_eager(DATA)) .select(nw.col(key).cast(value) for key, value in SCHEMA.items()) .lazy() .collect() @@ -159,10 +156,7 @@ def test_cast_series( result = df.select(df[col_].cast(dtype) for col_, dtype in cast_map.items()).schema for (key, ltype), rtype in zip(result.items(), cast_map.values()): - if ( - "modin_constructor" in str(nw_eager_constructor) - and key in MODIN_XFAIL_COLUMNS - ): + if "modin_constructor" in str(constructor_eager) and key in MODIN_XFAIL_COLUMNS: # TODO(unassigned): in modin we end up with `' None: def test_cast_raises_for_unknown_dtype( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(nw_frame_constructor): + if "duckdb" in str(constructor): request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (15,): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (15,): # Unsupported cast from string to dictionary using function cast_dictionary request.applymarker(pytest.mark.xfail) - if "pyspark" in str(nw_frame_constructor): + if "pyspark" in str(constructor): incompatible_columns = SPARK_LIKE_INCOMPATIBLE_COLUMNS # pragma: no cover - elif "ibis" in str(nw_frame_constructor): + elif "ibis" in str(constructor): incompatible_columns = IBIS_INCOMPATIBLE_COLUMNS # pragma: no cover else: incompatible_columns = set() @@ -201,7 +195,7 @@ def test_cast_raises_for_unknown_dtype( data = {k: v for k, v in DATA.items() if k not in incompatible_columns} schema = {k: v for k, v in SCHEMA.items() if k not in incompatible_columns} - df = nw.from_native(nw_frame_constructor(data)).select( + df = nw.from_native(constructor(data)).select( nw.col(key).cast(value) for key, value in schema.items() ) @@ -213,21 +207,18 @@ class Banana: def test_cast_datetime_tz_aware( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - "dask" in str(nw_frame_constructor) - or "duckdb" in str(nw_frame_constructor) - or "cudf" - in str(nw_frame_constructor) # https://github.com/rapidsai/cudf/issues/16973 - or "pyspark" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + "dask" in str(constructor) + or "duckdb" in str(constructor) + or "cudf" in str(constructor) # https://github.com/rapidsai/cudf/issues/16973 + or "pyspark" in str(constructor) + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) request.applymarker( - pytest.mark.xfail( - is_pyarrow_windows_no_tzdata(nw_frame_constructor), reason="no tzdata" - ) + pytest.mark.xfail(is_pyarrow_windows_no_tzdata(constructor), reason="no tzdata") ) data = { @@ -240,7 +231,7 @@ def test_cast_datetime_tz_aware( "date": ["2024-01-01 01:00:00", "2024-01-02 01:00:00", "2024-01-03 01:00:00"] } dtype = nw.Datetime(time_unit_compat("ms", request), time_zone="Europe/Rome") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("date").cast(dtype).cast(nw.String()).str.slice(offset=0, length=19) ) @@ -248,18 +239,16 @@ def test_cast_datetime_tz_aware( def test_cast_datetime_utc( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - "dask" in str(nw_frame_constructor) + "dask" in str(constructor) # https://github.com/eakmanrq/sqlframe/issues/406 - or "sqlframe" in str(nw_frame_constructor) + or "sqlframe" in str(constructor) ): request.applymarker(pytest.mark.xfail) request.applymarker( - pytest.mark.xfail( - is_pyarrow_windows_no_tzdata(nw_frame_constructor), reason="no tzdata" - ) + pytest.mark.xfail(is_pyarrow_windows_no_tzdata(constructor), reason="no tzdata") ) data = { @@ -272,20 +261,18 @@ def test_cast_datetime_utc( "date": ["2024-01-01 00:00:00", "2024-01-02 00:00:00", "2024-01-03 00:00:00"] } dtype = nw.Datetime(time_unit_compat("us", request), time_zone="UTC") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("date").cast(dtype).cast(nw.String()).str.slice(offset=0, length=19) ) assert_equal_data(result, expected) -def test_cast_struct( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_cast_struct(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") @@ -294,9 +281,9 @@ def test_cast_struct( [nw.Field("movie", nw.String()), nw.Field("rating", nw.Float64())] ) - if "spark" in str(nw_frame_constructor): + if "spark" in str(constructor): data = {"movie": ["Cars", "Toy Story"], "rating": [4.5, 4.9]} - dframe = nw.from_native(nw_frame_constructor(data)).select( + dframe = nw.from_native(constructor(data)).select( a=nw.struct("movie", "rating").cast(from_dtype) ) @@ -304,9 +291,7 @@ def test_cast_struct( data = { "a": [{"movie": "Cars", "rating": 4.5}, {"movie": "Toy Story", "rating": 4.9}] } - dframe = nw.from_native(nw_frame_constructor(data)).select( - nw.col("a").cast(from_dtype) - ) + dframe = nw.from_native(constructor(data)).select(nw.col("a").cast(from_dtype)) to_dtype = nw.Struct( [nw.Field("movie", nw.String()), nw.Field("rating", nw.Float32())] @@ -315,48 +300,42 @@ def test_cast_struct( assert result.collect_schema() == {"a": to_dtype} -def test_raise_if_polars_dtype(nw_frame_constructor: Constructor) -> None: +def test_raise_if_polars_dtype(constructor: Constructor) -> None: pytest.importorskip("polars") import polars as pl for dtype in [pl.String, pl.String()]: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(TypeError, match="Expected Narwhals dtype, got:"): df.select(nw.col("a").cast(dtype)) # type: ignore[arg-type] -def test_cast_time( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if "pandas" in str(nw_frame_constructor): +def test_cast_time(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if any( - backend in str(nw_frame_constructor) for backend in ("dask", "pyspark", "cudf") - ): + if any(backend in str(constructor) for backend in ("dask", "pyspark", "cudf")): request.applymarker(pytest.mark.xfail) data = {"a": [time(12, 0, 0), time(12, 0, 5)]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").cast(nw.Time())) assert result.collect_schema() == {"a": nw.Time()} -def test_cast_binary( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if "pandas" in str(nw_frame_constructor): +def test_cast_binary(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if any(backend in str(nw_frame_constructor) for backend in ("cudf", "dask")): + if any(backend in str(constructor) for backend in ("cudf", "dask")): request.applymarker(pytest.mark.xfail) data = {"a": ["test1", "test2"]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( "a", b=nw.col("a").cast(nw.Binary()), diff --git a/tests/expr_and_series/cat/get_categories_test.py b/tests/expr_and_series/cat/get_categories_test.py index 85bb42be94..6f984ff7ce 100644 --- a/tests/expr_and_series/cat/get_categories_test.py +++ b/tests/expr_and_series/cat/get_categories_test.py @@ -10,15 +10,15 @@ def test_get_categories_eager( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < (15, 0, 0): + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < (15, 0, 0): pytest.skip() - if "polars" in str(nw_eager_constructor): + if "polars" in str(constructor_eager): reason = "https://github.com/narwhals-dev/narwhals/issues/3097" request.applymarker(pytest.mark.xfail(reason=reason, strict=False)) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) df = df.select(nw.col("a").cast(nw.Categorical)) expected = {"a": ["one", "two"]} @@ -30,16 +30,16 @@ def test_get_categories_eager( def test_get_categories_lazy( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < (15, 0, 0): + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < (15, 0, 0): pytest.skip() - if "polars" in str(nw_eager_constructor): + if "polars" in str(constructor_eager): reason = "https://github.com/narwhals-dev/narwhals/issues/3097" request.applymarker(pytest.mark.xfail(reason=reason, strict=False)) - df = nw.from_native(nw_eager_constructor(data)).lazy() + df = nw.from_native(constructor_eager(data)).lazy() expr = nw.col("a").cast(nw.Categorical).cat.get_categories() msg = "Length-changing expressions are not supported for use in LazyFrame" with pytest.raises(InvalidOperationError, match=msg): diff --git a/tests/expr_and_series/clip_test.py b/tests/expr_and_series/clip_test.py index f2941a2ea7..382133f23c 100644 --- a/tests/expr_and_series/clip_test.py +++ b/tests/expr_and_series/clip_test.py @@ -18,19 +18,16 @@ ], ) def test_clip_expr( - nw_frame_constructor: Constructor, - lower: int | None, - upper: int | None, - expected: list[int], + constructor: Constructor, lower: int | None, upper: int | None, expected: list[int] ) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, -4, 5]})) + df = nw.from_native(constructor({"a": [1, 2, 3, -4, 5]})) result = df.select(result=nw.col("a").clip(lower_bound=lower, upper_bound=upper)) assert_equal_data(result, {"result": expected}) -def test_clip_expr_expressified(nw_frame_constructor: Constructor) -> None: +def test_clip_expr_expressified(constructor: Constructor) -> None: data = {"a": [1, 2, 3, -4, 5], "lb": [3, 2, 1, 1, 1], "ub": [4, 4, 2, 2, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").clip("lb", nw.col("ub") + 1)) expected_dict = {"a": [3, 2, 3, 1, 3]} assert_equal_data(result, expected_dict) @@ -47,26 +44,26 @@ def test_clip_expr_expressified(nw_frame_constructor: Constructor) -> None: ], ) def test_clip_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, lower: int | None, upper: int | None, expected: list[int], ) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, -4, 5]}), eager_only=True) + df = nw.from_native(constructor_eager({"a": [1, 2, 3, -4, 5]}), eager_only=True) result = {"result": df["a"].clip(lower_bound=lower, upper_bound=upper)} assert_equal_data(result, {"result": expected}) -def test_clip_series_expressified(nw_eager_constructor: ConstructorEager) -> None: +def test_clip_series_expressified(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3, -4, 5], "lb": [3, 2, 1, 1, 1], "ub": [4, 4, 2, 2, 2]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].clip(df["lb"], df["ub"] + 1).to_frame() expected_dict = {"a": [3, 2, 3, 1, 3]} assert_equal_data(result, expected_dict) -def test_clip_invalid(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_clip_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(nw.col("a").clip(nw.all(), nw.col("a", "b"))) diff --git a/tests/expr_and_series/coalesce_test.py b/tests/expr_and_series/coalesce_test.py index 24ce42bd50..5311b39c85 100644 --- a/tests/expr_and_series/coalesce_test.py +++ b/tests/expr_and_series/coalesce_test.py @@ -6,13 +6,13 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_coalesce_numeric(nw_frame_constructor: Constructor) -> None: +def test_coalesce_numeric(constructor: Constructor) -> None: data = { "a": [0, None, None, None, None], "b": [1, None, None, 5, 3], "c": [5, None, 3, 2, 1], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( no_lit=nw.coalesce("a", "b", "c"), @@ -22,13 +22,13 @@ def test_coalesce_numeric(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_coalesce_strings(nw_frame_constructor: Constructor) -> None: +def test_coalesce_strings(constructor: Constructor) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( no_lit=nw.coalesce("a", "b", "c"), @@ -41,41 +41,41 @@ def test_coalesce_strings(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_coalesce_series(nw_eager_constructor: ConstructorEager) -> None: +def test_coalesce_series(constructor_eager: ConstructorEager) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(result=nw.coalesce("a", "b", df["c"])) expected = {"result": ["0", None, "3", "5", "3"]} assert_equal_data(result, expected) -def test_coalesce_raises_non_expr(nw_frame_constructor: Constructor) -> None: +def test_coalesce_raises_non_expr(constructor: Constructor) -> None: data = { "a": ["0", None, None, None, None], "b": ["1", None, None, "5", "3"], "c": ["5", None, "3", "2", "1"], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(TypeError, match="All arguments to `coalesce` must be of type"): df.select(implicit_lit=nw.coalesce("a", "b", "c", 10)) def test_coalesce_multi_output( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3277 - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # Dask infers the type to be `string` :shrug: # https://github.com/narwhals-dev/narwhals/issues/3279 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "col1": [True, None, False, False, None], "col2": [True, False, True, False, None], diff --git a/tests/expr_and_series/concat_str_test.py b/tests/expr_and_series/concat_str_test.py index 4ca1940137..91e359c8fb 100644 --- a/tests/expr_and_series/concat_str_test.py +++ b/tests/expr_and_series/concat_str_test.py @@ -21,16 +21,16 @@ ], ) def test_concat_str( - nw_frame_constructor: Constructor, + constructor: Constructor, *, ignore_nulls: bool, expected: list[str], request: pytest.FixtureRequest, ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): # nth only available after 1.0 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select( "a", @@ -61,8 +61,8 @@ def test_concat_str( assert_equal_data(result, {"a": expected}) -def test_concat_str_with_lit(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": ["cat", "dog", "pig"]})) +def test_concat_str_with_lit(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": ["cat", "dog", "pig"]})) result = df.with_columns(b=nw.concat_str("a", nw.lit("ab"))) expected = {"a": ["cat", "dog", "pig"], "b": ["catab", "dogab", "pigab"]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/corr_test.py b/tests/expr_and_series/corr_test.py index 572a6d908f..15e371d62d 100644 --- a/tests/expr_and_series/corr_test.py +++ b/tests/expr_and_series/corr_test.py @@ -20,18 +20,18 @@ ], ) def test_corr_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, output_name: str, a: str | nw.Expr, b: str | nw.Expr, expected_corr: float | None, ) -> None: - if "pyspark" in str(nw_frame_constructor) and expected_corr is None: + if "pyspark" in str(constructor) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.corr(a, b).round(2)) expected = {output_name: [expected_corr]} assert_equal_data(result, expected) @@ -47,7 +47,7 @@ def test_corr_expr( ], ) def test_corr_expr_spearman( - nw_frame_constructor: Constructor, + constructor: Constructor, output_name: str, a: str | nw.Expr, b: str | nw.Expr, @@ -55,12 +55,10 @@ def test_corr_expr_spearman( ) -> None: context = ( does_not_raise() - if any( - x in str(nw_frame_constructor) for x in ("pandas", "polars", "modin", "cudf") - ) + if any(x in str(constructor) for x in ("pandas", "polars", "modin", "cudf")) else pytest.raises(NotImplementedError) ) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with context: result = df.select(nw.corr(a, b, method="spearman").round(2)) expected = {output_name: [expected_corr]} @@ -72,18 +70,18 @@ def test_corr_expr_spearman( [("a", "a", "b", 0.87), ("a", "a", "c", None)], ) def test_corr_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, output_name: str, a: str, b: str, expected_corr: float | None, ) -> None: - if "pyspark" in str(nw_eager_constructor) and expected_corr is None: + if "pyspark" in str(constructor_eager) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.corr(df[a], df[b]).round(2)) expected = {output_name: [expected_corr]} assert_equal_data(result, expected) @@ -94,26 +92,26 @@ def test_corr_series( [("a", "a", "b", 0.87), ("a", "a", "c", None)], ) def test_corr_series_spearman( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, output_name: str, a: str, b: str, expected_corr: float | None, ) -> None: - if "pyspark" in str(nw_eager_constructor) and expected_corr is None: + if "pyspark" in str(constructor_eager) and expected_corr is None: request.applymarker( pytest.skip(reason="Pyspark corr function does not allow None values") ) context = ( does_not_raise() if any( - x in str(nw_eager_constructor) + x in str(constructor_eager) for x in ("pandas", "polars", "modin", "cudf", "pyarrow") ) else pytest.raises(NotImplementedError) ) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) with context: result = df.select(nw.corr(df[a], df[b]).round(2)) expected = {output_name: [expected_corr]} diff --git a/tests/expr_and_series/cos_test.py b/tests/expr_and_series/cos_test.py index 93a04bff4a..4aa936d9bf 100644 --- a/tests/expr_and_series/cos_test.py +++ b/tests/expr_and_series/cos_test.py @@ -23,15 +23,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_cos_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_cos_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").cos()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_cos_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_cos_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.cos() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/count_test.py b/tests/expr_and_series/count_test.py index 015258fe88..c3f34ee132 100644 --- a/tests/expr_and_series/count_test.py +++ b/tests/expr_and_series/count_test.py @@ -4,17 +4,17 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_count(nw_frame_constructor: Constructor) -> None: +def test_count(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, None, 6], "z": [7.0, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b", "z").count()) expected = {"a": [3], "b": [2], "z": [1]} assert_equal_data(result, expected) -def test_count_series(nw_eager_constructor: ConstructorEager) -> None: +def test_count_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, None, 6], "z": [7.0, None, None]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"a": [df["a"].count()], "b": [df["b"].count()], "z": [df["z"].count()]} expected = {"a": [3], "b": [2], "z": [1]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/cum_count_test.py b/tests/expr_and_series/cum_count_test.py index de725ddbc6..f25c27f1c3 100644 --- a/tests/expr_and_series/cum_count_test.py +++ b/tests/expr_and_series/cum_count_test.py @@ -17,16 +17,16 @@ @pytest.mark.parametrize("reverse", [True, False]) -def test_cum_count_expr(nw_eager_constructor: ConstructorEager, *, reverse: bool) -> None: +def test_cum_count_expr(constructor_eager: ConstructorEager, *, reverse: bool) -> None: name = "reverse_cum_count" if reverse else "cum_count" - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").cum_count(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) -def test_cum_count_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_cum_count_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( cum_count=df["a"].cum_count(), reverse_cum_count=df["a"].cum_count(reverse=True) ) @@ -38,30 +38,30 @@ def test_cum_count_series(nw_eager_constructor: ConstructorEager) -> None: ("reverse", "expected_a"), [(False, [1, 1, 2]), (True, [1, 2, 1])] ) def test_lazy_cum_count_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "arg entina": [None, 2, 3], "ban gkok": [1, 0, 2], diff --git a/tests/expr_and_series/cum_max_test.py b/tests/expr_and_series/cum_max_test.py index d9279d5fef..82cf5ba179 100644 --- a/tests/expr_and_series/cum_max_test.py +++ b/tests/expr_and_series/cum_max_test.py @@ -19,16 +19,13 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_max_expr( - request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, - *, - reverse: bool, + request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) name = "reverse_cum_max" if reverse else "cum_max" - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").cum_max(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -38,32 +35,30 @@ def test_cum_max_expr( ("reverse", "expected_a"), [(False, [2, 2, 3]), (True, [3, 3, 3])] ) def test_lazy_cum_max_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( - {"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]} - ) + constructor({"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]}) ) result = df.with_columns( nw.col("a").cum_max(reverse=reverse).over("g", order_by="b") @@ -77,30 +72,30 @@ def test_lazy_cum_max_grouped( [(False, [4, 4, 4, 4, 4, 4, 4]), (True, [3, 3, 3, 3, 2, 3, 4])], ) def test_lazy_cum_max_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 2, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -125,24 +120,24 @@ def test_lazy_cum_max_ordered_by_nulls( ("reverse", "expected_a"), [(False, [2, 2, 3]), (True, [3, 3, 3])] ) def test_lazy_cum_max_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor) and reverse: + if "dask" in str(constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) + constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) ).sort("i") result = df.with_columns( nw.col("a").cum_max(reverse=reverse).over(order_by="b") @@ -156,24 +151,24 @@ def test_lazy_cum_max_ungrouped( [(False, [4, None, 4, 4, 4, 4, 4]), (True, [3, None, 3, 3, 2, 3, 4])], ) def test_lazy_cum_max_ungrouped_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, None, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -193,12 +188,12 @@ def test_lazy_cum_max_ungrouped_ordered_by_nulls( def test_cum_max_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( cum_max=df["a"].cum_max(), reverse_cum_max=df["a"].cum_max(reverse=True) ) diff --git a/tests/expr_and_series/cum_min_test.py b/tests/expr_and_series/cum_min_test.py index fde996e161..43fc1f5b81 100644 --- a/tests/expr_and_series/cum_min_test.py +++ b/tests/expr_and_series/cum_min_test.py @@ -21,16 +21,13 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_min_expr( - request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, - *, - reverse: bool, + request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) name = "reverse_cum_min" if reverse else "cum_min" - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").cum_min(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -40,32 +37,30 @@ def test_cum_min_expr( ("reverse", "expected_a"), [(False, [1, 2, 1]), (True, [1, 1, 3])] ) def test_lazy_cum_min_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( - {"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]} - ) + constructor({"a": [1, 2, 3], "b": [1, 0, 2], "i": [0, 1, 2], "g": [1, 1, 1]}) ) result = df.with_columns( nw.col("a").cum_min(reverse=reverse).over("g", order_by="b") @@ -79,40 +74,36 @@ def test_lazy_cum_min_grouped( [(False, [1, 2, 1, None, 1, 2, 4]), (True, [1, 1, 2, None, 2, 1, 1])], ) def test_lazy_cum_min_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "pandas_nullable" in str(nw_frame_constructor): + if "pandas_nullable" in str(constructor): # https://github.com/pandas-dev/pandas/issues/62473 request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if ( - "pyarrow" in str(nw_frame_constructor) - and is_windows() - and PYARROW_VERSION < (22, 0) - ): + if "pyarrow" in str(constructor) and is_windows() and PYARROW_VERSION < (22, 0): # https://github.com/pandas-dev/pandas/issues/62477 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 2, 3, None, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -137,23 +128,23 @@ def test_lazy_cum_min_ordered_by_nulls( ("reverse", "expected_a"), [(False, [1, 2, 1]), (True, [1, 1, 3])] ) def test_lazy_cum_min_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor) and reverse: + if "dask" in str(constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) + constructor({"a": [2, 3, 1], "b": [0, 2, 1], "i": [1, 2, 0]}) ).sort("i") result = df.with_columns( nw.col("a").cum_min(reverse=reverse).over(order_by="b") @@ -167,23 +158,23 @@ def test_lazy_cum_min_ungrouped( [(False, [1, 2, 1, 1, 1, 2, 4]), (True, [1, 1, 2, 1, 2, 1, 1])], ) def test_lazy_cum_min_ungrouped_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 2, 3, 1, 2, 3, 4], "b": [1, -1, 3, 2, 5, 0, None], @@ -203,12 +194,12 @@ def test_lazy_cum_min_ungrouped_ordered_by_nulls( def test_cum_min_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( cum_min=df["a"].cum_min(), reverse_cum_min=df["a"].cum_min(reverse=True) ) diff --git a/tests/expr_and_series/cum_prod_test.py b/tests/expr_and_series/cum_prod_test.py index 07d7b0b362..778c48bc67 100644 --- a/tests/expr_and_series/cum_prod_test.py +++ b/tests/expr_and_series/cum_prod_test.py @@ -19,28 +19,25 @@ @pytest.mark.parametrize("reverse", [True, False]) def test_cum_prod_expr( - request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, - *, - reverse: bool, + request: pytest.FixtureRequest, constructor_eager: ConstructorEager, *, reverse: bool ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) name = "reverse_cum_prod" if reverse else "cum_prod" - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").cum_prod(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) def test_cum_prod_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(nw_eager_constructor): + if (PANDAS_VERSION < (2, 1)) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( cum_prod=df["a"].cum_prod(), reverse_cum_prod=df["a"].cum_prod(reverse=True) ) @@ -51,33 +48,33 @@ def test_cum_prod_series( ("reverse", "expected_a"), [(False, [2, 2, 6, None]), (True, [3, 6, 3, None])] ) def test_lazy_cum_prod_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="probably bugged") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): # https://github.com/ibis-project/ibis/issues/10542 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "arg entina": [1, 2, 3, None], "ban gkok": [1, 0, 2, 3], diff --git a/tests/expr_and_series/cum_sum_test.py b/tests/expr_and_series/cum_sum_test.py index 243868a585..f3f0f780db 100644 --- a/tests/expr_and_series/cum_sum_test.py +++ b/tests/expr_and_series/cum_sum_test.py @@ -18,9 +18,9 @@ @pytest.mark.parametrize("reverse", [True, False]) -def test_cum_sum_expr(nw_eager_constructor: ConstructorEager, *, reverse: bool) -> None: +def test_cum_sum_expr(constructor_eager: ConstructorEager, *, reverse: bool) -> None: name = "reverse_cum_sum" if reverse else "cum_sum" - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("arg entina").cum_sum(reverse=reverse).alias(name)) assert_equal_data(result, {name: expected[name]}) @@ -30,28 +30,28 @@ def test_cum_sum_expr(nw_eager_constructor: ConstructorEager, *, reverse: bool) ("reverse", "expected_a"), [(False, [3, 2, 6]), (True, [4, 6, 3])] ) def test_lazy_cum_sum_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "arg entina": [1, 2, 3], "ban gkok": [1, 0, 2], @@ -77,38 +77,34 @@ def test_lazy_cum_sum_grouped( [(False, [None, 6, 13, 10, 15, 9, 4]), (True, [None, 11, 5, 6, 2, 9, 15])], ) def test_lazy_cum_sum_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "pyarrow_table" in str(nw_frame_constructor): + if "pyarrow_table" in str(constructor): # grouped window functions not yet supported request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if "pandas_nullable" in str(nw_frame_constructor) and not reverse: + if "pandas_nullable" in str(constructor) and not reverse: # https://github.com/pandas-dev/pandas/issues/62473 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if ( - "pyarrow" in str(nw_frame_constructor) - and is_windows() - and PYARROW_VERSION < (22, 0) - ): + if "pyarrow" in str(constructor) and is_windows() and PYARROW_VERSION < (22, 0): # https://github.com/pandas-dev/pandas/issues/62477 request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_frame_constructor( + constructor( { "arg entina": [None, 2, 3, 1, 2, 3, 4], "ban gkok": [1, -1, 3, 2, 5, 0, None], @@ -133,24 +129,22 @@ def test_lazy_cum_sum_ordered_by_nulls( ("reverse", "expected_a"), [(False, [3, 2, 6]), (True, [4, 6, 3])] ) def test_lazy_cum_sum_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor) and reverse: + if "dask" in str(constructor) and reverse: # https://github.com/dask/dask/issues/11802 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor( - {"arg entina": [2, 3, 1], "ban gkok": [0, 2, 1], "i ran": [1, 2, 0]} - ) + constructor({"arg entina": [2, 3, 1], "ban gkok": [0, 2, 1], "i ran": [1, 2, 0]}) ).sort("i ran") result = df.with_columns( nw.col("arg entina").cum_sum(reverse=reverse).over(order_by="ban gkok") @@ -164,22 +158,22 @@ def test_lazy_cum_sum_ungrouped( [(False, [10, 6, 14, 11, 16, 9, 4]), (True, [7, 12, 5, 6, 2, 10, 16])], ) def test_lazy_cum_sum_ungrouped_ordered_by_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, *, reverse: bool, expected_a: list[int], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11806 request.applymarker(pytest.mark.xfail) - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 9)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 9)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor( + constructor( { "arg entina": [1, 2, 3, 1, 2, 3, 4], "ban gkok": [1, -1, 3, 2, 5, 0, None], @@ -198,8 +192,8 @@ def test_lazy_cum_sum_ungrouped_ordered_by_nulls( assert_equal_data(result, expected) -def test_cum_sum_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_cum_sum_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( cum_sum=df["arg entina"].cum_sum(), reverse_cum_sum=df["arg entina"].cum_sum(reverse=True), @@ -207,11 +201,11 @@ def test_cum_sum_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_shift_cum_sum(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): +def test_shift_cum_sum(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() data = {"arg entina": [1, 2, 3, 4, 5], "i": list(range(5))} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.with_columns(kalimantan=nw.col("arg entina").shift(1).cum_sum()) expected = { "arg entina": [1, 2, 3, 4, 5], diff --git a/tests/expr_and_series/diff_test.py b/tests/expr_and_series/diff_test.py index 0c25a92243..dc7440541e 100644 --- a/tests/expr_and_series/diff_test.py +++ b/tests/expr_and_series/diff_test.py @@ -14,8 +14,8 @@ data = {"i": [0, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1]} -def test_diff(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_diff(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.with_columns(c_diff=nw.col("c").diff()).filter(nw.col("i") > 0) expected = { "i": [1, 2, 3, 4], @@ -26,13 +26,13 @@ def test_diff(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_diff_lazy(nw_frame_constructor: Constructor) -> None: +def test_diff_lazy(constructor: Constructor) -> None: data = {"i": [None, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1]} - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(c_diff=nw.col("c").diff().over(order_by="i")).filter( ~nw.col("i").is_null() ) @@ -46,19 +46,19 @@ def test_diff_lazy(nw_frame_constructor: Constructor) -> None: def test_diff_lazy_grouped( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): # https://github.com/dask/dask/issues/11806 # https://github.com/rapidsai/cudf/issues/18160 # wooah their issue numbers use exactly the same digits but in a different order request.applymarker(pytest.mark.xfail) data = {"i": [0, 1, 2, 3, 4], "b": [1, 1, 1, 2, 2], "c": [5, 4, 3, 2, 1]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns(c_diff=nw.col("c").diff().over("b", order_by="i")) .filter(nw.col("i") > 0) @@ -73,8 +73,8 @@ def test_diff_lazy_grouped( assert_equal_data(result, expected) -def test_diff_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_diff_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = { "i": [1, 2, 3, 4], "b": [2, 3, 5, 3], diff --git a/tests/expr_and_series/division_by_zero_test.py b/tests/expr_and_series/division_by_zero_test.py index 1f4e81473f..6e8313b522 100644 --- a/tests/expr_and_series/division_by_zero_test.py +++ b/tests/expr_and_series/division_by_zero_test.py @@ -19,10 +19,10 @@ @pytest.mark.parametrize("get_denominator", [lambda _: 0, lambda df: df["denominator"]]) def test_series_truediv_by_zero( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, get_denominator: Callable[[nw.DataFrame[Any]], int | nw.Series[Any]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) denominator = get_denominator(df) result = {"int": df["int"] / denominator, "float": df["float"] / denominator} expected = {"int": expected_truediv, "float": expected_truediv} @@ -31,9 +31,9 @@ def test_series_truediv_by_zero( @pytest.mark.parametrize("denominator", [0, nw.lit(0), nw.col("denominator")]) def test_expr_truediv_by_zero( - nw_frame_constructor: Constructor, denominator: int | nw.Expr + constructor: Constructor, denominator: int | nw.Expr ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("int", "float") / denominator) expected = {"int": expected_truediv, "float": expected_truediv} assert_equal_data(result, expected) @@ -41,13 +41,13 @@ def test_expr_truediv_by_zero( @pytest.mark.parametrize("get_denominator", [lambda _: 0, lambda df: df["denominator"]]) def test_series_floordiv_by_zero( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, get_denominator: Callable[[nw.DataFrame[Any]], int | nw.Series[Any]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if df.implementation.is_pandas_like(): request.applymarker(pytest.mark.xfail) @@ -60,13 +60,11 @@ def test_series_floordiv_by_zero( @pytest.mark.parametrize("denominator", [0, nw.lit(0), nw.col("denominator")]) def test_expr_floordiv_by_zero( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - denominator: int | nw.Expr, + constructor: Constructor, request: pytest.FixtureRequest, denominator: int | nw.Expr ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if df.implementation.is_pandas_like(): request.applymarker(pytest.mark.xfail) @@ -84,9 +82,9 @@ def test_expr_floordiv_by_zero( ), ) def test_series_rtruediv_by_zero( - nw_eager_constructor: ConstructorEager, numerator: float, expected: float + constructor_eager: ConstructorEager, numerator: float, expected: float ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"result": numerator / df["denominator"]} assert_equal_data(result, {"result": [expected] * len(df)}) @@ -98,9 +96,9 @@ def test_series_rtruediv_by_zero( ), ) def test_expr_rtruediv_by_zero( - nw_frame_constructor: Constructor, numerator: float, expected: float + constructor: Constructor, numerator: float, expected: float ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(result=numerator / nw.col("denominator")) assert_equal_data(result, {"result": [expected] * len(data["denominator"])}) assert_equal_data(result.select((~nw.all().is_finite()).all()), {"result": [True]}) @@ -108,25 +106,22 @@ def test_expr_rtruediv_by_zero( @pytest.mark.parametrize("numerator", data["int"]) def test_series_rfloordiv_by_zero( - nw_eager_constructor: ConstructorEager, - request: pytest.FixtureRequest, - numerator: float, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, numerator: float ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if any( - x in str(nw_eager_constructor) - for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") + x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") ) or ( any( - x in str(nw_eager_constructor) + x in str(constructor_eager) for x in ("pandas_nullable", "pandas_constructor", "modin_constructor") ) and numerator != 0 ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"result": numerator // df["denominator"]} assert_equal_data(result, {"result": expected_floordiv}) @@ -134,23 +129,22 @@ def test_series_rfloordiv_by_zero( @pytest.mark.parametrize("numerator", data["int"]) def test_expr_rfloordiv_by_zero( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest, numerator: float + constructor: Constructor, request: pytest.FixtureRequest, numerator: float ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): pytest.skip(reason="bug") if any( - x in str(nw_frame_constructor) - for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") + x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow", "cudf") ) or ( any( - x in str(nw_frame_constructor) + x in str(constructor) for x in ("pandas_nullable", "pandas_constructor", "modin_constructor") ) and numerator != 0 ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(result=numerator // nw.col("denominator")) expected = {"result": expected_floordiv} diff --git a/tests/expr_and_series/double_selected_test.py b/tests/expr_and_series/double_selected_test.py index 72dd6314e4..48b76222ec 100644 --- a/tests/expr_and_series/double_selected_test.py +++ b/tests/expr_and_series/double_selected_test.py @@ -7,9 +7,9 @@ from tests.utils import Constructor, assert_equal_data -def test_double_selected(nw_frame_constructor: Constructor) -> None: +def test_double_selected(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7, 8, 9]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b") * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12]} diff --git a/tests/expr_and_series/double_test.py b/tests/expr_and_series/double_test.py index 517d1c351e..de6a1afb09 100644 --- a/tests/expr_and_series/double_test.py +++ b/tests/expr_and_series/double_test.py @@ -4,17 +4,17 @@ from tests.utils import Constructor, assert_equal_data -def test_double(nw_frame_constructor: Constructor) -> None: +def test_double(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0]} assert_equal_data(result, expected) -def test_double_alias(nw_frame_constructor: Constructor) -> None: +def test_double_alias(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a").alias("o"), nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0], "o": [1, 3, 2]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/drop_nulls_test.py b/tests/expr_and_series/drop_nulls_test.py index f8e663d694..d067552eb6 100644 --- a/tests/expr_and_series/drop_nulls_test.py +++ b/tests/expr_and_series/drop_nulls_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_drop_nulls(nw_eager_constructor: ConstructorEager) -> None: +def test_drop_nulls(constructor_eager: ConstructorEager) -> None: data = { "A": [1, 2, None, 4], "B": [5, 6, 7, 8], @@ -14,7 +14,7 @@ def test_drop_nulls(nw_eager_constructor: ConstructorEager) -> None: "D": [9, 10, 11, 12], } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result_a = df.select(nw.col("A").drop_nulls()) result_b = df.select(nw.col("B").drop_nulls()) @@ -31,10 +31,8 @@ def test_drop_nulls(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result_d, expected_d) -def test_drop_nulls_agg( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): +def test_drop_nulls_agg(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) data = { "A": [1, 2, None, 4], @@ -43,13 +41,13 @@ def test_drop_nulls_agg( "D": [9, 10, 11, 12], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.all().drop_nulls().len()) expected = {"A": [3], "B": [4], "C": [0], "D": [4]} assert_equal_data(result, expected) -def test_drop_nulls_series(nw_eager_constructor: ConstructorEager) -> None: +def test_drop_nulls_series(constructor_eager: ConstructorEager) -> None: data = { "A": [1, 2, None, 4], "B": [5, 6, 7, 8], @@ -57,7 +55,7 @@ def test_drop_nulls_series(nw_eager_constructor: ConstructorEager) -> None: "D": [9, 10, 11, 12], } - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_a = df.select(df["A"].drop_nulls()) result_b = df.select(df["B"].drop_nulls()) diff --git a/tests/expr_and_series/dt/convert_time_zone_test.py b/tests/expr_and_series/dt/convert_time_zone_test.py index d9074f89f0..8fd654ad6d 100644 --- a/tests/expr_and_series/dt/convert_time_zone_test.py +++ b/tests/expr_and_series/dt/convert_time_zone_test.py @@ -21,16 +21,16 @@ def test_convert_time_zone( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pyarrow_table" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -38,7 +38,7 @@ def test_convert_time_zone( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.convert_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -50,16 +50,16 @@ def test_convert_time_zone( def test_convert_time_zone_series( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(nw_eager_constructor) and is_windows()) - or ("pyarrow_table" in str(nw_eager_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(constructor_eager) and is_windows()) + or ("pyarrow_table" in str(constructor_eager) and is_windows()) + or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(nw_eager_constructor) for x in ("cudf",)): + if any(x in str(constructor_eager) for x in ("cudf",)): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -67,7 +67,7 @@ def test_convert_time_zone_series( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.convert_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -79,18 +79,18 @@ def test_convert_time_zone_series( def test_convert_time_zone_from_none( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pyarrow_table" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("cudf", "duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7): # polars used to disallow this pytest.skip() data = { @@ -99,7 +99,7 @@ def test_convert_time_zone_from_none( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").dt.replace_time_zone(None).dt.convert_time_zone("Asia/Kathmandu") ) @@ -112,26 +112,26 @@ def test_convert_time_zone_from_none( assert_equal_data(result_str, expected) -def test_convert_time_zone_to_none(nw_frame_constructor: Constructor) -> None: +def test_convert_time_zone_to_none(constructor: Constructor) -> None: data = { "a": [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(TypeError, match="Target `time_zone` cannot be `None`"): df.select(nw.col("a").dt.convert_time_zone(None)) # type: ignore[arg-type] -def test_convert_time_zone_to_none_series(nw_eager_constructor: ConstructorEager) -> None: +def test_convert_time_zone_to_none_series(constructor_eager: ConstructorEager) -> None: data = { "a": [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) with pytest.raises(TypeError, match="Target `time_zone` cannot be `None`"): df["a"].dt.convert_time_zone(None) # type: ignore[arg-type] diff --git a/tests/expr_and_series/dt/datetime_attributes_test.py b/tests/expr_and_series/dt/datetime_attributes_test.py index cc6f867db4..c7bf55e7c0 100644 --- a/tests/expr_and_series/dt/datetime_attributes_test.py +++ b/tests/expr_and_series/dt/datetime_attributes_test.py @@ -35,22 +35,22 @@ ) def test_datetime_attributes( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, attribute: str, expected: list[int], ) -> None: if ( attribute == "date" - and "pandas" in str(nw_frame_constructor) - and "pyarrow" not in str(nw_frame_constructor) + and "pandas" in str(constructor) + and "pyarrow" not in str(constructor) ): request.applymarker(pytest.mark.xfail) - if attribute == "date" and "cudf" in str(nw_frame_constructor): + if attribute == "date" and "cudf" in str(constructor): request.applymarker(pytest.mark.xfail) - if attribute == "nanosecond" and "ibis" in str(nw_frame_constructor): + if attribute == "nanosecond" and "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a").dt, attribute)()) assert_equal_data(result, {"a": expected}) @@ -74,39 +74,35 @@ def test_datetime_attributes( ) def test_datetime_attributes_series( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, attribute: str, expected: list[int], ) -> None: if ( attribute == "date" - and "pandas" in str(nw_eager_constructor) - and "pyarrow" not in str(nw_eager_constructor) + and "pandas" in str(constructor_eager) + and "pyarrow" not in str(constructor_eager) ): request.applymarker(pytest.mark.xfail) - if attribute == "date" and "cudf" in str(nw_eager_constructor): + if attribute == "date" and "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(getattr(df["a"].dt, attribute)()) assert_equal_data(result, {"a": expected}) def test_datetime_chained_attributes( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pandas" in str(nw_eager_constructor) and "pyarrow" not in str( - nw_eager_constructor - ): + if "pandas" in str(constructor_eager) and "pyarrow" not in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_eager_constructor) and "pyarrow" not in str( - nw_eager_constructor - ): + if "modin" in str(constructor_eager) and "pyarrow" not in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.date().dt.year()) assert_equal_data(result, {"a": [2021, 2020]}) @@ -114,11 +110,9 @@ def test_datetime_chained_attributes( assert_equal_data(result, {"a": [2021, 2020]}) -def test_to_date( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: +def test_to_date(request: pytest.FixtureRequest, constructor: Constructor) -> None: if any( - x in str(nw_frame_constructor) + x in str(constructor) for x in ( "pandas_constructor", "pandas_nullable_constructor", @@ -128,11 +122,11 @@ def test_to_date( ): request.applymarker(pytest.mark.xfail) dates = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - if "dask" in str(nw_frame_constructor): - df_dask = cast("dd.DataFrame", nw_frame_constructor(dates)) + if "dask" in str(constructor): + df_dask = cast("dd.DataFrame", constructor(dates)) df_dask = cast("dd.DataFrame", df_dask.astype({"a": "timestamp[ns][pyarrow]"})) df = nw.from_native(df_dask) else: - df = nw.from_native(nw_frame_constructor(dates)) + df = nw.from_native(constructor(dates)) result = df.select(nw.col("a").dt.date()) assert result.collect_schema() == {"a": nw.Date} diff --git a/tests/expr_and_series/dt/datetime_duration_test.py b/tests/expr_and_series/dt/datetime_duration_test.py index 2f1dfeaa59..b84ecfa66e 100644 --- a/tests/expr_and_series/dt/datetime_duration_test.py +++ b/tests/expr_and_series/dt/datetime_duration_test.py @@ -26,19 +26,19 @@ ) def test_duration_attributes( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, attribute: str, expected_a: list[int], expected_b: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_frame_constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor): pytest.skip() - if "pyspark" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): + if "pyspark" in str(constructor) or "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and attribute == "total_nanoseconds": + if "duckdb" in str(constructor) and attribute == "total_nanoseconds": request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_a = df.select(getattr(nw.col("a").dt, attribute)().fill_null(0)) assert_equal_data(result_a, {"a": expected_a}) @@ -59,22 +59,22 @@ def test_duration_attributes( ) def test_duration_attributes_nano( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, attribute: str, expected_c: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_frame_constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor): pytest.skip() - if "pyspark" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): + if "pyspark" in str(constructor) or "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and attribute == "total_nanoseconds": + if "duckdb" in str(constructor) and attribute == "total_nanoseconds": request.applymarker(pytest.mark.xfail) pytest.importorskip("numpy") import numpy as np data = {"c": np.array([None, 20], dtype="timedelta64[ns]")} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_c = df.select(getattr(nw.col("c").dt, attribute)().fill_null(0)) assert_equal_data(result_c, {"c": expected_c}) @@ -92,15 +92,15 @@ def test_duration_attributes_nano( ) def test_duration_attributes_series( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, attribute: str, expected_a: list[int], expected_b: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_eager_constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_a = df.select(getattr(df["a"].dt, attribute)().fill_null(0)) assert_equal_data(result_a, {"a": expected_a}) @@ -121,18 +121,18 @@ def test_duration_attributes_series( ) def test_duration_attributes_series_nano( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, attribute: str, expected_c: list[int], ) -> None: - if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(nw_eager_constructor): + if PANDAS_VERSION < (2, 2) and "pandas_pyarrow" in str(constructor_eager): request.applymarker(pytest.mark.xfail) pytest.importorskip("numpy") import numpy as np data = {"c": np.array([None, 20], dtype="timedelta64[ns]")} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_c = df.select(getattr(df["c"].dt, attribute)().fill_null(0)) assert_equal_data(result_c, {"c": expected_c}) diff --git a/tests/expr_and_series/dt/offset_by_test.py b/tests/expr_and_series/dt/offset_by_test.py index 55888dbd67..9085edb185 100644 --- a/tests/expr_and_series/dt/offset_by_test.py +++ b/tests/expr_and_series/dt/offset_by_test.py @@ -135,25 +135,24 @@ ) def test_offset_by( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, by: str, expected: list[datetime], ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() if any(x in by for x in ("y", "q", "mo")) and any( - x in str(nw_frame_constructor) for x in ("dask", "pyarrow", "ibis") + x in str(constructor) for x in ("dask", "pyarrow", "ibis") ): request.applymarker(pytest.mark.xfail()) if "ns" in by and any( - x in str(nw_frame_constructor) - for x in ("dask", "pyspark", "ibis", "cudf", "duckdb") + x in str(constructor) for x in ("dask", "pyspark", "ibis", "cudf", "duckdb") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask", "ibis")): + if by.endswith("d") and any(x in str(constructor) for x in ("dask", "ibis")): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": expected}) @@ -168,31 +167,26 @@ def test_offset_by( ], ) def test_offset_by_tz( - request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, - by: str, - expected: str, + request: pytest.FixtureRequest, constructor: Constructor, by: str, expected: str ) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pyarrow_table" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any( - x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "sqlframe", "ibis") - ): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "sqlframe", "ibis")): # pyspark,duckdb don't support changing time zones. # convert_time_zone is not supported for ibis. request.applymarker(pytest.mark.xfail()) if any(x in by for x in ("y", "q", "mo")) and any( - x in str(nw_frame_constructor) for x in ("dask", "pyarrow", "ibis") + x in str(constructor) for x in ("dask", "pyarrow", "ibis") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask",)): + if by.endswith("d") and any(x in str(constructor) for x in ("dask",)): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(nw_frame_constructor(data_tz)) + df = nw.from_native(constructor(data_tz)) df = df.select(nw.col("a").dt.convert_time_zone("Asia/Kathmandu")) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": [datetime.strptime(expected, "%Y-%m-%dT%H:%M%z")]}) @@ -207,41 +201,36 @@ def test_offset_by_tz( ], ) def test_offset_by_dst( - request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, - by: str, - expected: str, + request: pytest.FixtureRequest, constructor: Constructor, by: str, expected: str ) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pyarrow_table" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pyarrow_table" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1)) ): pytest.skip() - if any( - x in str(nw_frame_constructor) for x in ("duckdb", "sqlframe", "pyspark", "ibis") - ): + if any(x in str(constructor) for x in ("duckdb", "sqlframe", "pyspark", "ibis")): # pyspark,duckdb don't support changing time zones. # convert_time_zone is not supported for ibis. request.applymarker(pytest.mark.xfail()) - if any(x in str(nw_frame_constructor) for x in ("cudf",)) and "d" not in by: + if any(x in str(constructor) for x in ("cudf",)) and "d" not in by: # cudf: https://github.com/rapidsai/cudf/issues/19363 request.applymarker(pytest.mark.xfail()) if any(x in by for x in ("y", "q", "mo")) and any( - x in str(nw_frame_constructor) for x in ("dask", "pyarrow") + x in str(constructor) for x in ("dask", "pyarrow") ): request.applymarker(pytest.mark.xfail()) - if by.endswith("d") and any(x in str(nw_frame_constructor) for x in ("dask",)): + if by.endswith("d") and any(x in str(constructor) for x in ("dask",)): request.applymarker(pytest.mark.xfail()) - df = nw.from_native(nw_frame_constructor(data_dst)) + df = nw.from_native(constructor(data_dst)) df = df.with_columns(a=nw.col("a").dt.convert_time_zone("Europe/Amsterdam")) result = df.select(nw.col("a").dt.offset_by(by)) assert_equal_data(result, {"a": [datetime.strptime(expected, "%Y-%m-%dT%H:%M%z")]}) -def test_offset_by_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_offset_by_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.offset_by("1h")) expected = { "a": [ @@ -252,10 +241,10 @@ def test_offset_by_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_offset_by_invalid_interval(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_offset_by_invalid_interval(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) msg = "Invalid `every` string" with pytest.raises(ValueError, match=msg): df.select(nw.col("a").dt.offset_by("1r")) @@ -277,14 +266,12 @@ def test_offset_by_date_pandas() -> None: assert_equal_data(result, expected) -def test_offset_by_3471( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if any(x in str(nw_frame_constructor) for x in ("dask", "ibis")): +def test_offset_by_3471(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if any(x in str(constructor) for x in ("dask", "ibis")): request.applymarker(pytest.mark.xfail()) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - date_nw = nw.from_native(nw_frame_constructor({"date": [date(2026, 1, 31)]})) + date_nw = nw.from_native(constructor({"date": [date(2026, 1, 31)]})) existent_col_offset = nw.col("date").dt.offset_by("-1d") result = date_nw.with_columns(existent_col_offset) diff --git a/tests/expr_and_series/dt/replace_time_zone_test.py b/tests/expr_and_series/dt/replace_time_zone_test.py index ed8bddf5c1..27bc394b69 100644 --- a/tests/expr_and_series/dt/replace_time_zone_test.py +++ b/tests/expr_and_series/dt/replace_time_zone_test.py @@ -15,16 +15,16 @@ def test_replace_time_zone( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("cudf", "pyspark", "ibis", "duckdb")): + if any(x in str(constructor) for x in ("cudf", "pyspark", "ibis", "duckdb")): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -32,7 +32,7 @@ def test_replace_time_zone( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -43,11 +43,11 @@ def test_replace_time_zone( assert_equal_data(result_str, expected) -def test_replace_time_zone_none(nw_frame_constructor: Constructor) -> None: +def test_replace_time_zone_none(constructor: Constructor) -> None: if ( - ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(constructor) and is_windows()) + or ("pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(constructor) and PANDAS_VERSION < (2,)) ): pytest.skip() data = { @@ -56,7 +56,7 @@ def test_replace_time_zone_none(nw_frame_constructor: Constructor) -> None: datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.replace_time_zone(None)) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -68,15 +68,15 @@ def test_replace_time_zone_none(nw_frame_constructor: Constructor) -> None: def test_replace_time_zone_series( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pyarrow" in str(nw_eager_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(constructor_eager) and is_windows()) + or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) ): pytest.skip() - if any(x in str(nw_eager_constructor) for x in ("cudf",)): + if any(x in str(constructor_eager) for x in ("cudf",)): request.applymarker(pytest.mark.xfail) data = { "a": [ @@ -84,7 +84,7 @@ def test_replace_time_zone_series( datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.replace_time_zone("Asia/Kathmandu")) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime @@ -95,11 +95,11 @@ def test_replace_time_zone_series( assert_equal_data(result_str, expected) -def test_replace_time_zone_none_series(nw_eager_constructor: ConstructorEager) -> None: +def test_replace_time_zone_none_series(constructor_eager: ConstructorEager) -> None: if ( - ("pyarrow" in str(nw_eager_constructor) and is_windows()) - or ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) - or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2,)) + ("pyarrow" in str(constructor_eager) and is_windows()) + or ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) + or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2,)) ): pytest.skip() data = { @@ -108,7 +108,7 @@ def test_replace_time_zone_none_series(nw_eager_constructor: ConstructorEager) - datetime(2020, 1, 2, tzinfo=timezone.utc), ] } - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.replace_time_zone(None)) result_dtype = result.collect_schema()["a"] assert result_dtype == nw.Datetime diff --git a/tests/expr_and_series/dt/timestamp_test.py b/tests/expr_and_series/dt/timestamp_test.py index f08c694a64..e199fcac76 100644 --- a/tests/expr_and_series/dt/timestamp_test.py +++ b/tests/expr_and_series/dt/timestamp_test.py @@ -45,27 +45,27 @@ ) def test_timestamp_datetimes( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, original_time_unit: Literal["us", "ns", "ms", "s"], time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) - if original_time_unit == "s" and "polars" in str(nw_frame_constructor): + if original_time_unit == "s" and "polars" in str(constructor): pytest.skip("Second precision not supported in Polars") - if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < ( + if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < ( 2, 2, ): # pragma: no cover pytest.skip("Requires pandas >= 2.2 for reliable pyarrow-backed timestamps") datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - df = nw.from_native(nw_frame_constructor(datetimes)) + df = nw.from_native(constructor(datetimes)) dtype = nw.Datetime(time_unit_compat(original_time_unit, request)) result = df.select(nw.col("a").cast(dtype).dt.timestamp(time_unit)) assert_equal_data(result, {"a": expected}) @@ -90,32 +90,32 @@ def test_timestamp_datetimes( ) def test_timestamp_datetimes_tz_aware( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, original_time_unit: Literal["us", "ns", "ms", "s"], time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) version_conditions = [ ( - is_pyarrow_windows_no_tzdata(nw_frame_constructor), + is_pyarrow_windows_no_tzdata(constructor), "Timezone database is not installed on Windows", ), ( - "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2,), + "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2,), "Requires pandas >= 2.0 for pyarrow support", ), ( - "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 2), + "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 2), "Requires pandas >= 2.2 for reliable timestamps", ), ( - "dask" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1), + "dask" in str(constructor) and PANDAS_VERSION < (2, 1), "Requires pandas >= 2.1 for dask support", ), ] @@ -124,10 +124,10 @@ def test_timestamp_datetimes_tz_aware( if condition: pytest.skip(reason) # pragma: no cover - if original_time_unit == "s" and "polars" in str(nw_frame_constructor): + if original_time_unit == "s" and "polars" in str(constructor): pytest.skip() datetimes = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - df = nw.from_native(nw_frame_constructor(datetimes)) + df = nw.from_native(constructor(datetimes)) dtype = nw.Datetime(time_unit_compat(original_time_unit, request)) result = df.select( nw.col("a") @@ -149,13 +149,13 @@ def test_timestamp_datetimes_tz_aware( ) def test_timestamp_dates( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, time_unit: Literal["ns", "us", "ms"], expected: list[int | None], ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) @@ -165,30 +165,30 @@ def test_timestamp_dates( "cudf", "modin_constructor", ) - if any(x in str(nw_frame_constructor) for x in unsupported_backends): + if any(x in str(constructor) for x in unsupported_backends): pytest.skip("Backend does not support date type") dates = {"a": [datetime(2001, 1, 1), None, datetime(2001, 1, 3)]} - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): df = nw.from_native( - nw_frame_constructor(dates).astype({"a": "timestamp[ns][pyarrow]"}) # type: ignore[union-attr] + constructor(dates).astype({"a": "timestamp[ns][pyarrow]"}) # type: ignore[union-attr] ) else: - df = nw.from_native(nw_frame_constructor(dates)) + df = nw.from_native(constructor(dates)) result = df.select(nw.col("a").dt.date().dt.timestamp(time_unit)) assert_equal_data(result, {"a": expected}) def test_timestamp_invalid_date( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): pytest.skip(reason="https://github.com/narwhals-dev/narwhals/issues/2808") - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker( pytest.mark.xfail(reason="Backend timestamp conversion not yet implemented") ) - if "polars" in str(nw_frame_constructor): + if "polars" in str(constructor): request.applymarker( pytest.mark.xfail( reason="Invalid date handling not yet implemented in Polars" @@ -196,8 +196,8 @@ def test_timestamp_invalid_date( ) data_str = {"a": ["x", "y", None]} data_num = {"a": [1, 2, None]} - df_str = nw.from_native(nw_frame_constructor(data_str)) - df_num = nw.from_native(nw_frame_constructor(data_num)) + df_str = nw.from_native(constructor(data_str)) + df_num = nw.from_native(constructor(data_num)) msg = "Input should be either of Date or Datetime type" with pytest.raises(TypeError, match=msg): df_str.select(nw.col("a").dt.timestamp()) @@ -205,26 +205,26 @@ def test_timestamp_invalid_date( df_num.select(nw.col("a").dt.timestamp()) -def test_timestamp_invalid_unit_expr(nw_frame_constructor: Constructor) -> None: +def test_timestamp_invalid_unit_expr(constructor: Constructor) -> None: time_unit_invalid = "i" msg = ( "invalid `time_unit`" f"\n\nExpected one of {{'ns', 'us', 'ms'}}, got {time_unit_invalid!r}." ) with pytest.raises(ValueError, match=msg): - nw.from_native(nw_frame_constructor(data)).select( + nw.from_native(constructor(data)).select( nw.col("a").dt.timestamp(time_unit_invalid) # type: ignore[arg-type] ) -def test_timestamp_invalid_unit_series(nw_eager_constructor: ConstructorEager) -> None: +def test_timestamp_invalid_unit_series(constructor_eager: ConstructorEager) -> None: time_unit_invalid = "i" msg = ( "invalid `time_unit`" f"\n\nExpected one of {{'ns', 'us', 'ms'}}, got {time_unit_invalid!r}." ) with pytest.raises(ValueError, match=msg): - nw.from_native(nw_eager_constructor(data))["a"].dt.timestamp(time_unit_invalid) # type: ignore[arg-type] + nw.from_native(constructor_eager(data))["a"].dt.timestamp(time_unit_invalid) # type: ignore[arg-type] @given( diff --git a/tests/expr_and_series/dt/to_string_test.py b/tests/expr_and_series/dt/to_string_test.py index f9d6d210a1..4fd4c14c66 100644 --- a/tests/expr_and_series/dt/to_string_test.py +++ b/tests/expr_and_series/dt/to_string_test.py @@ -17,8 +17,8 @@ "fmt", ["%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%G-W%V-%u", "%G-W%V"] ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") -def test_dt_to_string_series(nw_eager_constructor: ConstructorEager, fmt: str) -> None: - input_frame = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_dt_to_string_series(constructor_eager: ConstructorEager, fmt: str) -> None: + input_frame = nw.from_native(constructor_eager(data), eager_only=True) input_series = input_frame["a"] expected_col = [datetime.strftime(d, fmt) for d in data["a"]] @@ -26,8 +26,7 @@ def test_dt_to_string_series(nw_eager_constructor: ConstructorEager, fmt: str) - result = {"a": input_series.dt.to_string(fmt)} if any( - x in str(nw_eager_constructor) - for x in ["pandas_pyarrow", "pyarrow_table", "modin"] + x in str(constructor_eager) for x in ["pandas_pyarrow", "pyarrow_table", "modin"] ): # PyArrow differs from other libraries, in that %S also shows # the fraction of a second. @@ -40,16 +39,13 @@ def test_dt_to_string_series(nw_eager_constructor: ConstructorEager, fmt: str) - "fmt", ["%Y-%m-%d", "%Y-%m-%d %H:%M:%S", "%Y/%m/%d %H:%M:%S", "%G-W%V-%u", "%G-W%V"] ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") -def test_dt_to_string_expr(nw_frame_constructor: Constructor, fmt: str) -> None: - input_frame = nw.from_native(nw_frame_constructor(data)) +def test_dt_to_string_expr(constructor: Constructor, fmt: str) -> None: + input_frame = nw.from_native(constructor(data)) expected_col = [datetime.strftime(d, fmt) for d in data["a"]] result = input_frame.select(nw.col("a").dt.to_string(fmt).alias("b")) - if any( - x in str(nw_frame_constructor) - for x in ["pandas_pyarrow", "pyarrow_table", "modin"] - ): + if any(x in str(constructor) for x in ["pandas_pyarrow", "pyarrow_table", "modin"]): # PyArrow differs from other libraries, in that %S also shows # the fraction of a second. result = input_frame.select( @@ -82,9 +78,9 @@ def _clean_string_expr(e: Any) -> Any: ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_datetime_series( - nw_eager_constructor: ConstructorEager, data: datetime, expected: str + constructor_eager: ConstructorEager, data: datetime, expected: str ) -> None: - df = nw_eager_constructor({"a": [data]}) + df = constructor_eager({"a": [data]}) result = ( nw.from_native(df, eager_only=True)["a"] .dt.to_string("%Y-%m-%dT%H:%M:%S.%f") @@ -110,14 +106,14 @@ def test_dt_to_string_iso_local_datetime_series( ) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_datetime_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, data: datetime, expected: str, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor): + if "duckdb" in str(constructor) or "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - df = nw_frame_constructor({"a": [data]}) + df = constructor({"a": [data]}) result = nw.from_native(df).select( b=_clean_string_expr(nw.col("a").dt.to_string("%Y-%m-%dT%H:%M:%S.%f")) @@ -133,9 +129,9 @@ def test_dt_to_string_iso_local_datetime_expr( @pytest.mark.parametrize(("data", "expected"), [(datetime(2020, 1, 9), "2020-01-09")]) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_date_series( - nw_eager_constructor: ConstructorEager, data: datetime, expected: str + constructor_eager: ConstructorEager, data: datetime, expected: str ) -> None: - df = nw_eager_constructor({"a": [data]}) + df = constructor_eager({"a": [data]}) result = nw.from_native(df, eager_only=True)["a"].dt.to_string("%Y-%m-%d").item(0) assert str(result) == expected @@ -143,8 +139,8 @@ def test_dt_to_string_iso_local_date_series( @pytest.mark.parametrize(("data", "expected"), [(datetime(2020, 1, 9), "2020-01-09")]) @pytest.mark.skipif(is_windows(), reason="pyarrow breaking on windows") def test_dt_to_string_iso_local_date_expr( - nw_frame_constructor: Constructor, data: datetime, expected: str + constructor: Constructor, data: datetime, expected: str ) -> None: - df = nw_frame_constructor({"a": [data]}) + df = constructor({"a": [data]}) result = nw.from_native(df).select(b=nw.col("a").dt.to_string("%Y-%m-%d")) assert_equal_data(result, {"b": [expected]}) diff --git a/tests/expr_and_series/dt/truncate_test.py b/tests/expr_and_series/dt/truncate_test.py index e9a750d39a..40ce18d428 100644 --- a/tests/expr_and_series/dt/truncate_test.py +++ b/tests/expr_and_series/dt/truncate_test.py @@ -48,27 +48,23 @@ ) def test_truncate( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, every: str, expected: list[datetime], ) -> None: if every.endswith("ns") and any( - x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis") + x in str(constructor) for x in ("duckdb", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail()) - if ( - every.endswith("ns") - and "polars" in str(nw_frame_constructor) - and POLARS_VERSION < (1, 35) - ): + if every.endswith("ns") and "polars" in str(constructor) and POLARS_VERSION < (1, 35): request.applymarker(pytest.mark.xfail()) if any(every.endswith(x) for x in ("mo", "q", "y")) and any( - x in str(nw_frame_constructor) for x in ("dask", "cudf") + x in str(constructor) for x in ("dask", "cudf") ): request.applymarker(pytest.mark.xfail(reason="Not implemented")) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.truncate(every)) assert_equal_data(result, {"a": expected}) @@ -107,34 +103,26 @@ def test_truncate( ) def test_truncate_multiples( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, every: str, expected: list[datetime], ) -> None: - if any(x in str(nw_frame_constructor) for x in ("cudf", "pyspark", "duckdb")): + if any(x in str(constructor) for x in ("cudf", "pyspark", "duckdb")): # Reasons: # - cudf: https://github.com/rapidsai/cudf/issues/18654 # - pyspark/sqlframe: Only multiple 1 is currently supported request.applymarker(pytest.mark.xfail()) - if every.endswith("ns") and any( - x in str(nw_frame_constructor) for x in ("duckdb", "ibis") - ): + if every.endswith("ns") and any(x in str(constructor) for x in ("duckdb", "ibis")): request.applymarker(pytest.mark.xfail()) - if ( - every.endswith("ns") - and "polars" in str(nw_frame_constructor) - and POLARS_VERSION < (1, 35) - ): + if every.endswith("ns") and "polars" in str(constructor) and POLARS_VERSION < (1, 35): request.applymarker(pytest.mark.xfail()) - if any(every.endswith(x) for x in ("mo", "q", "y")) and "dask" in str( - nw_frame_constructor - ): + if any(every.endswith(x) for x in ("mo", "q", "y")) and "dask" in str(constructor): request.applymarker(pytest.mark.xfail(reason="Not implemented")) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").dt.truncate(every)) assert_equal_data(result, {"a": expected}) @@ -169,8 +157,8 @@ def test_truncate_polars_ns(every: str, expected: list[datetime]) -> None: assert_equal_data(result, {"a": expected}) -def test_truncate_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_truncate_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].dt.truncate("1h")) expected = { "a": [datetime(2021, 3, 1, 12, 0, 0, 0), datetime(2020, 1, 2, 2, 0, 0, 0)] @@ -178,15 +166,15 @@ def test_truncate_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_truncate_invalid_interval(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_truncate_invalid_interval(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) msg = "Invalid `every` string" with pytest.raises(ValueError, match=msg): df.select(nw.col("a").dt.truncate("1r")) -def test_truncate_invalid_multiple(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_truncate_invalid_multiple(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) msg = "Only the following multiples are supported" msg_year = "Only multiple 1 is currently supported for 'y' unit" with pytest.raises(ValueError, match=msg): diff --git a/tests/expr_and_series/ewm_test.py b/tests/expr_and_series/ewm_test.py index 5a10c50624..a3afae154b 100644 --- a/tests/expr_and_series/ewm_test.py +++ b/tests/expr_and_series/ewm_test.py @@ -9,12 +9,12 @@ def test_ewm_mean_expr( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a", "b").ewm_mean(com=1)) expected = { "a": [1.0, 1.0, 1.5714285714285714], @@ -24,12 +24,12 @@ def test_ewm_mean_expr( def test_ewm_mean_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.ewm_mean(com=1) expected = {"a": [1.0, 1.0, 1.5714285714285714]} assert_equal_data({"a": result}, expected) @@ -50,14 +50,14 @@ def test_ewm_mean_series( ) def test_ewm_mean_expr_adjust( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, adjust: bool, # noqa: FBT001 expected: dict[str, list[float]], ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a", "b").ewm_mean(com=1, adjust=adjust)) assert_equal_data(result, expected) @@ -73,23 +73,23 @@ def test_ewm_mean_nulls( request: pytest.FixtureRequest, ignore_nulls: bool, # noqa: FBT001 expected: dict[str, list[float]], - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin", "cudf")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin", "cudf")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"a": [2.0, 4.0, None, 3.0]})) + df = nw.from_native(constructor_eager({"a": [2.0, 4.0, None, 3.0]})) result = df.select(nw.col("a").ewm_mean(com=1, ignore_nulls=ignore_nulls)) assert_equal_data(result, expected) def test_ewm_mean_params( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin", "cudf")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin", "cudf")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"a": [2, 5, 3]})) + df = nw.from_native(constructor_eager({"a": [2, 5, 3]})) expected: dict[str, list[float | None]] = {"a": [2.0, 4.0, 3.4285714285714284]} assert_equal_data( df.select(nw.col("a").ewm_mean(alpha=0.5, adjust=True, ignore_nulls=True)), diff --git a/tests/expr_and_series/exclude_test.py b/tests/expr_and_series/exclude_test.py index 40e3fbbda2..4aa39478d2 100644 --- a/tests/expr_and_series/exclude_test.py +++ b/tests/expr_and_series/exclude_test.py @@ -21,11 +21,11 @@ ], ) def test_exclude( - nw_frame_constructor: Constructor, exclude_selector: nw.Expr, expected_cols: list[str] + constructor: Constructor, exclude_selector: nw.Expr, expected_cols: list[str] ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(exclude_selector) expected = {col: data[col] for col in expected_cols} diff --git a/tests/expr_and_series/exp_test.py b/tests/expr_and_series/exp_test.py index 407c4843d6..7bfcd5c404 100644 --- a/tests/expr_and_series/exp_test.py +++ b/tests/expr_and_series/exp_test.py @@ -11,15 +11,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_exp_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_exp_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").exp()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_exp_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_exp_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.exp() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/fill_nan_test.py b/tests/expr_and_series/fill_nan_test.py index 7245d5fd3e..5d3ddc8cfc 100644 --- a/tests/expr_and_series/fill_nan_test.py +++ b/tests/expr_and_series/fill_nan_test.py @@ -6,10 +6,8 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_fill_nan( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if "cudf" in str(nw_frame_constructor): +def test_fill_nan(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if "cudf" in str(constructor): request.applymarker( pytest.mark.xfail( reason="https://github.com/narwhals-dev/narwhals/issues/3231", @@ -17,7 +15,7 @@ def test_fill_nan( ) ) data_na = {"int": [-1, 1, None]} - df = nw.from_native(nw_frame_constructor(data_na)).select( + df = nw.from_native(constructor(data_na)).select( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") ** 0.5 ) result = df.select(nw.all().fill_nan(None)) @@ -25,11 +23,11 @@ def test_fill_nan( assert_equal_data(result, expected) assert result.lazy().collect()["float_na"].null_count() == 2 result = df.select(nw.all().fill_nan(3.0)) - if nw_frame_constructor.is_non_nullable: + if constructor.is_non_nullable: # no nan vs null distinction expected = {"float": [-1.0, 1.0, 3.0], "float_na": [3.0, 1.0, 3.0]} assert result.lazy().collect()["float_na"].null_count() == 0 - elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): expected = {"float": [-1.0, 1.0, None], "float_na": [None, 1.0, None]} assert result.lazy().collect()["float_na"].null_count() == 2 else: @@ -38,16 +36,16 @@ def test_fill_nan( assert_equal_data(result, expected) -def test_fill_nan_series(nw_eager_constructor: ConstructorEager) -> None: +def test_fill_nan_series(constructor_eager: ConstructorEager) -> None: data_na = {"int": [-1, 1, None]} - s = nw.from_native(nw_eager_constructor(data_na)).select( - float_na=nw.col("int") ** 0.5 - )["float_na"] + s = nw.from_native(constructor_eager(data_na)).select(float_na=nw.col("int") ** 0.5)[ + "float_na" + ] result = s.fill_nan(999) - if nw_eager_constructor.is_non_nullable: + if constructor_eager.is_non_nullable: # no nan vs null distinction assert_equal_data({"a": result}, {"a": [999.0, 1.0, 999.0]}) - elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): assert_equal_data({"a": result}, {"a": [None, 1.0, None]}) else: assert_equal_data({"a": result}, {"a": [999.0, 1.0, None]}) diff --git a/tests/expr_and_series/fill_null_test.py b/tests/expr_and_series/fill_null_test.py index 2e04e40a0b..213b695176 100644 --- a/tests/expr_and_series/fill_null_test.py +++ b/tests/expr_and_series/fill_null_test.py @@ -20,13 +20,13 @@ from narwhals.typing import FillNullStrategy -def test_fill_null(nw_frame_constructor: Constructor) -> None: +def test_fill_null(constructor: Constructor) -> None: data = { "a": [0.0, None, 2.0, 3.0, 4.0], "b": [1.0, None, None, 5.0, 3.0], "c": [5.0, None, 3.0, 2.0, 1.0], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a", "b", "c").fill_null(value=99)) expected = { @@ -37,14 +37,14 @@ def test_fill_null(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_fill_null_w_aggregate(nw_frame_constructor: Constructor) -> None: - if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 12): +def test_fill_null_w_aggregate(constructor: Constructor) -> None: + if "dask" in str(constructor) and DASK_VERSION < (2024, 12): # Bug in old version of Dask. pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [0.5, None, 2.0, 3.0, 4.5], "b": ["xx", "yy", "zz", None, "yy"]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").fill_null(nw.col("a").mean()), nw.col("b").fill_null("a") @@ -64,13 +64,13 @@ def test_fill_null_pandas_downcast() -> None: assert result["a"].to_native().dtype == "object" -def test_fill_null_series_expression(nw_frame_constructor: Constructor) -> None: +def test_fill_null_series_expression(constructor: Constructor) -> None: data = { "a": [0.0, None, 2.0, 3.0, 4.0], "b": [1.0, None, None, 5.0, 3.0], "c": [5.0, 2.0, None, 2.0, 1.0], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a", "b").fill_null(nw.col("c"))) expected = { @@ -81,9 +81,9 @@ def test_fill_null_series_expression(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_fill_null_exceptions(nw_frame_constructor: Constructor) -> None: +def test_fill_null_exceptions(constructor: Constructor) -> None: data = {"a": [0.0, None, 2.0, 3.0, 4.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(ValueError, match="cannot specify both `value` and `strategy`"): df.with_columns(nw.col("a").fill_null(value=99, strategy="forward")) @@ -98,14 +98,14 @@ def test_fill_null_exceptions(nw_frame_constructor: Constructor) -> None: def test_fill_null_strategies_with_limit_as_none( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) data_limits = { @@ -113,7 +113,7 @@ def test_fill_null_strategies_with_limit_as_none( "b": ["a", None, None, None, "b", "c", None, None, None, "d"], "idx": list(range(10)), } - df = nw.from_native(nw_frame_constructor(data_limits)) + df = nw.from_native(constructor(data_limits)) expected_forward = { "a": [1, 1, 1, 1, 5, 6, 6, 6, 6, 10], @@ -121,9 +121,9 @@ def test_fill_null_strategies_with_limit_as_none( "idx": list(range(10)), } if ( - "pandas_pyarrow_constructor" in str(nw_frame_constructor) - or "modin" in str(nw_frame_constructor) - or "dask" in str(nw_frame_constructor) + "pandas_pyarrow_constructor" in str(constructor) + or "modin" in str(constructor) + or "dask" in str(constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -155,9 +155,9 @@ def test_fill_null_strategies_with_limit_as_none( "idx": list(range(10)), } if ( - "pandas_pyarrow_constructor" in str(nw_frame_constructor) - or "modin" in str(nw_frame_constructor) - or "dask" in str(nw_frame_constructor) + "pandas_pyarrow_constructor" in str(constructor) + or "modin" in str(constructor) + or "dask" in str(constructor) ): with warnings.catch_warnings(): # case for modin and dask @@ -185,21 +185,21 @@ def test_fill_null_strategies_with_limit_as_none( def test_fill_null_limits( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) context: Any = ( pytest.raises(NotImplementedError, match="The limit keyword is not supported") - if "cudf" in str(nw_frame_constructor) + if "cudf" in str(constructor) else warnings.catch_warnings() - if "modin" in str(nw_frame_constructor) + if "modin" in str(constructor) else does_not_raise() ) data_limits = { @@ -207,9 +207,9 @@ def test_fill_null_limits( "b": ["a", None, None, None, "b", "c", None, None, None, "d"], "idx": list(range(10)), } - df = nw.from_native(nw_frame_constructor(data_limits)) + df = nw.from_native(constructor(data_limits)) with context: - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): warnings.filterwarnings( "ignore", message="The 'downcast' keyword in fillna is deprecated" ) @@ -236,9 +236,9 @@ def test_fill_null_limits( assert_equal_data(result_backward, expected_backward) -def test_fill_null_series(nw_eager_constructor: ConstructorEager) -> None: +def test_fill_null_series(constructor_eager: ConstructorEager) -> None: data_series_float = {"a": [0.0, 1, None, 2, None, 3]} - df_float = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) + df_float = nw.from_native(constructor_eager(data_series_float), eager_only=True) expected_float = {"a_zero_digit": [0.0, 1, 0, 2, 0, 3]} result_float = df_float.select(a_zero_digit=df_float["a"].fill_null(value=0)) @@ -246,7 +246,7 @@ def test_fill_null_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result_float, expected_float) data_series_str = {"a": ["a", None, "c", None, "e"]} - df_str = nw.from_native(nw_eager_constructor(data_series_str), eager_only=True) + df_str = nw.from_native(constructor_eager(data_series_str), eager_only=True) expected_str = {"a_z_str": ["a", "z", "c", "z", "e"]} @@ -255,22 +255,22 @@ def test_fill_null_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result_str, expected_str) -def test_fill_null_series_limits(nw_eager_constructor: ConstructorEager) -> None: +def test_fill_null_series_limits(constructor_eager: ConstructorEager) -> None: context: Any = ( pytest.raises(NotImplementedError, match="The limit keyword is not supported") - if "cudf" in str(nw_eager_constructor) + if "cudf" in str(constructor_eager) else warnings.catch_warnings() - if "modin" in str(nw_eager_constructor) + if "modin" in str(constructor_eager) else does_not_raise() ) data_series_float = { "a": [0.0, 1, None, None, 2, None, None, 3], "b": ["", "a", None, None, "c", None, None, "e"], } - df = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) + df = nw.from_native(constructor_eager(data_series_float), eager_only=True) with context: - if "modin" in str(nw_eager_constructor): + if "modin" in str(constructor_eager): warnings.filterwarnings( "ignore", message="The 'downcast' keyword in fillna is deprecated" ) @@ -298,18 +298,18 @@ def test_fill_null_series_limits(nw_eager_constructor: ConstructorEager) -> None assert_equal_data(result_backward, expected_backward) -def test_fill_null_series_limit_as_none(nw_eager_constructor: ConstructorEager) -> None: +def test_fill_null_series_limit_as_none(constructor_eager: ConstructorEager) -> None: data_series = {"a": [1, None, None, None, 5, 6, None, None, None, 10]} - df = nw.from_native(nw_eager_constructor(data_series), eager_only=True) + df = nw.from_native(constructor_eager(data_series), eager_only=True) expected_forward = { "a_forward": [1, 1, 1, 1, 5, 6, 6, 6, 6, 10], "a_backward": [1, 5, 5, 5, 5, 6, 10, 10, 10, 10], } if ( - "pandas_pyarrow_constructor" in str(nw_eager_constructor) - or "modin" in str(nw_eager_constructor) - or "dask" in str(nw_eager_constructor) + "pandas_pyarrow_constructor" in str(constructor_eager) + or "modin" in str(constructor_eager) + or "dask" in str(constructor_eager) ): with warnings.catch_warnings(): # case for modin and dask @@ -335,7 +335,7 @@ def test_fill_null_series_limit_as_none(nw_eager_constructor: ConstructorEager) data_series_str = {"a": ["a", None, None, None, "b", "c", None, None, None, "d"]} - df_str = nw.from_native(nw_eager_constructor(data_series_str), eager_only=True) + df_str = nw.from_native(constructor_eager(data_series_str), eager_only=True) expected_forward_str = { "a_forward": ["a", "a", "a", "a", "b", "c", "c", "c", "c", "d"], @@ -343,9 +343,9 @@ def test_fill_null_series_limit_as_none(nw_eager_constructor: ConstructorEager) } if ( - "pandas_pyarrow_constructor" in str(nw_eager_constructor) - or "modin" in str(nw_eager_constructor) - or "dask" in str(nw_eager_constructor) + "pandas_pyarrow_constructor" in str(constructor_eager) + or "modin" in str(constructor_eager) + or "dask" in str(constructor_eager) ): with warnings.catch_warnings(): # case for modin and dask @@ -369,9 +369,9 @@ def test_fill_null_series_limit_as_none(nw_eager_constructor: ConstructorEager) assert_equal_data(result_forward_str, expected_forward_str) -def test_fill_null_series_exceptions(nw_eager_constructor: ConstructorEager) -> None: +def test_fill_null_series_exceptions(constructor_eager: ConstructorEager) -> None: data_series_float = {"a": [0.0, 1, None, 2, None, 3]} - df_float = nw.from_native(nw_eager_constructor(data_series_float), eager_only=True) + df_float = nw.from_native(constructor_eager(data_series_float), eager_only=True) with pytest.raises(ValueError, match="cannot specify both `value` and `strategy`"): df_float.select(a_zero_digit=df_float["a"].fill_null(value=0, strategy="forward")) @@ -388,16 +388,16 @@ def test_fill_null_series_exceptions(nw_eager_constructor: ConstructorEager) -> def test_fill_null_strategies_with_partition_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "ibis")): + if any(x in str(constructor) for x in ("pyarrow_table", "dask", "ibis")): request.applymarker(pytest.mark.xfail) - if ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) or ( - "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10) + if ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) or ( + "polars" in str(constructor) and POLARS_VERSION < (1, 10) ): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() @@ -406,7 +406,7 @@ def test_fill_null_strategies_with_partition_by( "values": [1, None, None, 2, None, 3, None, None, 4], "idx": list(range(9)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) # Forward fill within each group result_forward = df.with_columns( @@ -447,21 +447,21 @@ def test_fill_null_strategies_with_partition_by( ], ) def test_fill_null_expr_limits( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, values: list[int | None], strategy: FillNullStrategy, limit: int, expected: list[int | None], request: pytest.FixtureRequest, ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): reason = "The limit keyword is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) data = {"a": values} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.with_columns(nw.col("a").fill_null(strategy=strategy, limit=limit)) assert_equal_data(result, {"a": expected}) diff --git a/tests/expr_and_series/filter_test.py b/tests/expr_and_series/filter_test.py index ccfcdb5c7b..5f300ed4b8 100644 --- a/tests/expr_and_series/filter_test.py +++ b/tests/expr_and_series/filter_test.py @@ -20,15 +20,15 @@ } -def test_filter(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_filter(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").filter(nw.col("i") < 2, nw.col("c") == 5)) expected = {"a": [0]} assert_equal_data(result, expected) -def test_filter_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_filter_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].filter((df["i"] < 2) & (df["c"] == 5))) expected = {"a": [0]} assert_equal_data(result, expected) @@ -37,8 +37,8 @@ def test_filter_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data({"a": result_s}, expected) -def test_filter_constraints(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_constraints(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result_added = df.filter(nw.col("i") < 4, b=3) expected = {"i": [2], "a": [2], "b": [3], "c": [3]} assert_equal_data(result_added, expected) @@ -46,10 +46,10 @@ def test_filter_constraints(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_only, expected) -def test_filter_windows(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_filter_windows(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.filter(nw.col("i") == nw.col("i").min()) expected = {"i": [0], "a": [0], "b": [1], "c": [5]} assert_equal_data(result, expected) @@ -60,12 +60,12 @@ def test_filter_windows(nw_frame_constructor: Constructor) -> None: def test_filter_windows_over( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): request.applymarker(pytest.mark.xfail()) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.filter(nw.col("i") == nw.col("i").min().over("b")).sort("i") assert_equal_data(result, expected_over) diff --git a/tests/expr_and_series/first_last_test.py b/tests/expr_and_series/first_last_test.py index e5f323aa82..0dab322cd1 100644 --- a/tests/expr_and_series/first_last_test.py +++ b/tests/expr_and_series/first_last_test.py @@ -35,20 +35,20 @@ @single_cases def test_first_last_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.first() assert_equal_data({col: [result]}, {col: [expected_first]}) result = series.last() assert_equal_data({col: [result]}, {col: [expected_last]}) -def test_first_last_series_empty(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_first_last_series_empty(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] series = series.filter(series > 50) result = series.first() assert result is None @@ -58,12 +58,12 @@ def test_first_last_series_empty(nw_eager_constructor: ConstructorEager) -> None @single_cases def test_first_last_expr_select( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select( nw.col(col).first().name.suffix("_first"), nw.col(col).last().name.suffix("_last") ) @@ -74,12 +74,12 @@ def test_first_last_expr_select( @single_cases def test_first_expr_with_columns( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, col: str, expected_first: PythonLiteral, expected_last: PythonLiteral, ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.with_columns( nw.col(col).first().name.suffix("_first"), nw.col(col).last().name.suffix("_last") ).select(nw.selectors.matches("first|last")) @@ -93,22 +93,22 @@ def test_first_expr_with_columns( def test_first_last_expr_over_order_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): + if any(x in str(constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): reason = "Need to pass dtype when passing pd.NA or None" request.applymarker(pytest.mark.xfail(reason=reason)) frame = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 1, 2], "b": [4, 5, 6], @@ -150,24 +150,24 @@ def test_first_last_expr_over_order_by( def test_first_expr_over_order_by_partition_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): + if any(x in str(constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): # https://github.com/ibis-project/ibis/issues/11656 request.applymarker(pytest.mark.xfail) frame = nw.from_native( - nw_frame_constructor( + constructor( {"a": [1, 1, 2], "b": [4, 5, 6], "c": [None, 7, 8], "i": [1, None, 2]} ) ) @@ -189,14 +189,14 @@ def test_first_expr_over_order_by_partition_by( def test_first_expr_in_group_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("spark", "dask")): + if any(x in str(constructor) for x in ("spark", "dask")): # ibis: https://github.com/ibis-project/ibis/issues/11656 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): pytest.skip() data = { "grp": [1, 1, 1, 2], @@ -206,7 +206,7 @@ def test_first_expr_in_group_by( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.group_by("grp") .agg( @@ -246,11 +246,11 @@ def test_first_expr_in_group_by( def test_first_expr_broadcasting( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("spark", "dask")): + if any(x in str(constructor) for x in ("spark", "dask")): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { @@ -261,7 +261,7 @@ def test_first_expr_broadcasting( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( "idx", "idx2", nw.col("a", "b", "c").first(order_by="idx").name.suffix("_first") ).sort("idx", "idx2") @@ -289,9 +289,9 @@ def test_first_expr_broadcasting( def test_first_expr_invalid( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): request.applymarker(pytest.mark.xfail) data = { "grp": [1, 1, 1, 2], @@ -301,31 +301,31 @@ def test_first_expr_invalid( "idx": [9, None, None, 7], "idx2": [9, 8, 7, 7], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(InvalidOperationError, match="expression which isn't orderable"): df.select("idx", "idx2", nw.col("a").first(order_by="idx").over(order_by="idx2")) def test_first_last_different_orders( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("pyspark", "dask")): + if any(x in str(constructor) for x in ("pyspark", "dask")): # Currently unsupported. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14,): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14,): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() context = ( pytest.raises(NotImplementedError, match="Only one `order_by` can") - if "pandas" in str(nw_frame_constructor) or "pyarrow" in str(nw_frame_constructor) + if "pandas" in str(constructor) or "pyarrow" in str(constructor) else does_not_raise() ) frame = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 1, 2], "b": [4, 5, 6], diff --git a/tests/expr_and_series/floor_ceil_test.py b/tests/expr_and_series/floor_ceil_test.py index d7871df9a6..ae0df72712 100644 --- a/tests/expr_and_series/floor_ceil_test.py +++ b/tests/expr_and_series/floor_ceil_test.py @@ -6,9 +6,9 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_floor_expr(nw_frame_constructor: Constructor) -> None: +def test_floor_expr(constructor: Constructor) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) expected_data = {"a": [1.0, 2.0, 3.0, -1.0]} @@ -17,9 +17,9 @@ def test_floor_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_frame, expected_data) -def test_ceil_expr(nw_frame_constructor: Constructor) -> None: +def test_ceil_expr(constructor: Constructor) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) expected_data = {"a": [2.0, 3.0, 4.0, 0.0]} @@ -27,9 +27,9 @@ def test_ceil_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_frame, expected_data) -def test_floor_series(nw_eager_constructor: ConstructorEager) -> None: +def test_floor_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {"a": [1.0, 2.0, 3.0, -1.0]} @@ -38,9 +38,9 @@ def test_floor_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data({"a": result_series}, expected_data) -def test_ceil_series(nw_eager_constructor: ConstructorEager) -> None: +def test_ceil_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1.12345, 2.56789, 3.901234, -0.5]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {"a": [2.0, 3.0, 4.0, 0.0]} diff --git a/tests/expr_and_series/format_test.py b/tests/expr_and_series/format_test.py index e6ac2bef19..5bd4ba75a9 100644 --- a/tests/expr_and_series/format_test.py +++ b/tests/expr_and_series/format_test.py @@ -6,9 +6,9 @@ from tests.utils import Constructor, assert_equal_data -def test_format(nw_frame_constructor: Constructor) -> None: +def test_format(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor( + constructor( { "name": ["bob", "alice", "dodo"], "surname": ["builder", "wonderlander", "extinct"], diff --git a/tests/expr_and_series/horizontal_broadcasts_test.py b/tests/expr_and_series/horizontal_broadcasts_test.py index 18cc88de85..6c6bb8966d 100644 --- a/tests/expr_and_series/horizontal_broadcasts_test.py +++ b/tests/expr_and_series/horizontal_broadcasts_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_sumh_broadcasting(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_sumh_broadcasting(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6], "i": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns( any=nw.any_horizontal(nw.sum("a", "b").cast(nw.Boolean), ignore_nulls=True), all=nw.all_horizontal(nw.sum("a", "b").cast(nw.Boolean), ignore_nulls=True), diff --git a/tests/expr_and_series/is_between_test.py b/tests/expr_and_series/is_between_test.py index f99f76438a..6cec08ad64 100644 --- a/tests/expr_and_series/is_between_test.py +++ b/tests/expr_and_series/is_between_test.py @@ -20,20 +20,20 @@ ], ) def test_is_between( - nw_frame_constructor: Constructor, + constructor: Constructor, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [1, 4, 2, 5]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_between(1, 5, closed=closed)) expected_dict = {"a": expected} assert_equal_data(result, expected_dict) -def test_is_between_expressified(nw_frame_constructor: Constructor) -> None: +def test_is_between_expressified(constructor: Constructor) -> None: data = {"a": [1, 4, 2, 5], "b": [0, 5, 2, 4], "c": [9, 9, 9, 9]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_between(nw.col("b") * 0.9, "c")) expected_dict = {"a": [True, False, True, True]} assert_equal_data(result, expected_dict) @@ -49,20 +49,20 @@ def test_is_between_expressified(nw_frame_constructor: Constructor) -> None: ], ) def test_is_between_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [1, 4, 2, 5]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.with_columns(a=df["a"].is_between(1, 5, closed=closed)) expected_dict = {"a": expected} assert_equal_data(result, expected_dict) -def test_is_between_expressified_series(nw_eager_constructor: ConstructorEager) -> None: +def test_is_between_expressified_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 4, 2, 5], "b": [0, 5, 2, 4], "c": [9, 9, 9, 9]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].is_between(df["b"], df["c"]).to_frame() expected_dict = {"a": [True, False, True, True]} assert_equal_data(result, expected_dict) @@ -78,12 +78,12 @@ def test_is_between_expressified_series(nw_eager_constructor: ConstructorEager) ], ) def test_is_between_datetimes( - nw_frame_constructor: Constructor, + constructor: Constructor, closed: Literal["left", "right", "none", "both"], expected: list[bool], ) -> None: data = {"a": [datetime(2020, 1, 1), datetime(2020, 6, 1)]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").is_between(datetime(2020, 3, 1), datetime(2020, 6, 1), closed=closed) ) @@ -91,7 +91,7 @@ def test_is_between_datetimes( assert_equal_data(result, expected_dict) -def test_is_between_invalid(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_is_between_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(nw.col("a").is_between(nw.all(), nw.col("a", "b"))) diff --git a/tests/expr_and_series/is_close_test.py b/tests/expr_and_series/is_close_test.py index 5dcbf68d70..6cfdb94657 100644 --- a/tests/expr_and_series/is_close_test.py +++ b/tests/expr_and_series/is_close_test.py @@ -35,10 +35,8 @@ # Exceptions -def test_is_close_series_raise_non_numeric( - nw_eager_constructor: ConstructorEager, -) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_is_close_series_raise_non_numeric(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) x, y = df["non_numeric"], df["y"] msg = "`is_close` operation not supported for dtype" @@ -48,9 +46,9 @@ def test_is_close_series_raise_non_numeric( @pytest.mark.parametrize("rel_tol", [1e-09, 999]) def test_is_close_raise_negative_abs_tol( - nw_eager_constructor: ConstructorEager, rel_tol: float + constructor_eager: ConstructorEager, rel_tol: float ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) x, y = df["x"], df["y"] abs_tol = -2 @@ -64,9 +62,9 @@ def test_is_close_raise_negative_abs_tol( @pytest.mark.parametrize("rel_tol", [-0.0001, 1.0, 1.1]) def test_is_close_raise_invalid_rel_tol( - nw_eager_constructor: ConstructorEager, rel_tol: float + constructor_eager: ConstructorEager, rel_tol: float ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) x, y = df["x"], df["y"] msg = rf"`rel_tol` must be in the range \[0, 1\) but got {rel_tol}" @@ -100,14 +98,14 @@ def test_is_close_raise_invalid_rel_tol( # Series @cases_columnar def test_is_close_series_with_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, abs_tol: float, rel_tol: float, *, nans_equal: bool, expected: list[Any], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) x, y = df["x"], df["y"] nulls = nw.new_series( "nulls", [None] * len(x), nw.Float64(), backend=df.implementation @@ -116,9 +114,9 @@ def test_is_close_series_with_series( y = y.zip_with(y != NAN_PLACEHOLDER, y**0.5).zip_with(y != NULL_PLACEHOLDER, nulls) result = x.is_close(y, abs_tol=abs_tol, rel_tol=rel_tol, nans_equal=nans_equal) - if nw_eager_constructor.is_non_nullable: + if constructor_eager.is_non_nullable: expected = [v if v is not None else nans_equal for v in expected] - elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -128,7 +126,7 @@ def test_is_close_series_with_series( @cases_scalar def test_is_close_series_with_scalar( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, other: NumericLiteral, abs_tol: float, rel_tol: float, @@ -136,7 +134,7 @@ def test_is_close_series_with_scalar( nans_equal: bool, expected: list[Any], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) y = df["y"] nulls = nw.new_series( "nulls", [None] * len(y), nw.Float64(), backend=df.implementation @@ -144,9 +142,9 @@ def test_is_close_series_with_scalar( y = y.zip_with(y != NAN_PLACEHOLDER, y**0.5).zip_with(y != NULL_PLACEHOLDER, nulls) result = y.is_close(other, abs_tol=abs_tol, rel_tol=rel_tol, nans_equal=nans_equal) - if nw_eager_constructor.is_non_nullable: + if constructor_eager.is_non_nullable: expected = [v if v is not None else False for v in expected] - elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -158,14 +156,14 @@ def test_is_close_series_with_scalar( @cases_columnar def test_is_close_expr_with_expr( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, abs_tol: float, rel_tol: float, *, nans_equal: bool, expected: list[Any], ) -> None: - if "sqlframe" in str(nw_frame_constructor): + if "sqlframe" in str(constructor): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='" @@ -174,7 +172,7 @@ def test_is_close_expr_with_expr( x, y = nw.col("x"), nw.col("y") result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_columns( x=nw.when(x != NAN_PLACEHOLDER).then(x).otherwise(x**0.5), y=nw.when(y != NAN_PLACEHOLDER).then(y).otherwise(y**0.5), @@ -189,9 +187,9 @@ def test_is_close_expr_with_expr( ) .sort("idx") ) - if nw_frame_constructor.is_non_nullable: + if constructor.is_non_nullable: expected = [v if v is not None else nans_equal for v in expected] - elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -202,7 +200,7 @@ def test_is_close_expr_with_expr( @cases_scalar def test_is_close_expr_with_scalar( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, other: NumericLiteral, abs_tol: float, rel_tol: float, @@ -210,7 +208,7 @@ def test_is_close_expr_with_scalar( nans_equal: bool, expected: list[Any], ) -> None: - if "sqlframe" in str(nw_frame_constructor): + if "sqlframe" in str(constructor): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='" @@ -219,7 +217,7 @@ def test_is_close_expr_with_scalar( y = nw.col("y") result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_columns(y=nw.when(y != NAN_PLACEHOLDER).then(y).otherwise(y**0.5)) .with_columns(y=nw.when(y != NULL_PLACEHOLDER).then(y)) .select( @@ -230,9 +228,9 @@ def test_is_close_expr_with_scalar( ) .sort("idx") ) - if nw_frame_constructor.is_non_nullable: + if constructor.is_non_nullable: expected = [v if v is not None else False for v in expected] - elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): expected = [ v if data["y"][i] not in {NULL_PLACEHOLDER, NAN_PLACEHOLDER} else None for i, v in enumerate(expected) @@ -252,8 +250,8 @@ def test_is_close_pandas_unnamed() -> None: assert res.name == "ab" -def test_issue_3474_series_decimal(nw_eager_constructor: ConstructorEager) -> None: - frame = nw.from_native(nw_eager_constructor({"a": [0, 1, 2]})) +def test_issue_3474_series_decimal(constructor_eager: ConstructorEager) -> None: + frame = nw.from_native(constructor_eager({"a": [0, 1, 2]})) if frame.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) @@ -265,9 +263,9 @@ def test_issue_3474_series_decimal(nw_eager_constructor: ConstructorEager) -> No def test_issue_3474_expr_decimal( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("dask", "sqlframe")): + if any(x in str(constructor) for x in ("dask", "sqlframe")): # TODO(FBruzzesi): Figure out a MRE and report upstream reason = ( "SQLFrame: duckdb.duckdb.ParserException: Parser Error: syntax error at or near '='\n" @@ -275,7 +273,7 @@ def test_issue_3474_expr_decimal( ) request.applymarker(pytest.mark.xfail(reason=reason)) - frame = nw.from_native(nw_frame_constructor({"a": [0, 1, 2]})) + frame = nw.from_native(constructor({"a": [0, 1, 2]})) if frame.implementation.is_pandas_like() and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 2) diff --git a/tests/expr_and_series/is_duplicated_test.py b/tests/expr_and_series/is_duplicated_test.py index c99f990ff8..42f07a91e5 100644 --- a/tests/expr_and_series/is_duplicated_test.py +++ b/tests/expr_and_series/is_duplicated_test.py @@ -6,31 +6,31 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_is_duplicated_expr(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_is_duplicated_expr(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").is_duplicated(), "index").sort("index") expected = {"a": [True, True, False], "b": [False, False, False], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_duplicated_w_nulls_expr(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_is_duplicated_w_nulls_expr(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, None], "b": [1, None, None], "index": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").is_duplicated(), "index").sort("index") expected = {"a": [True, True, False], "b": [False, True, True], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_duplicated_series(nw_eager_constructor: ConstructorEager) -> None: +def test_is_duplicated_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.is_duplicated() expected = {"a": [True, True, False]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_finite_test.py b/tests/expr_and_series/is_finite_test.py index bff9923e58..b2a36d5ed7 100644 --- a/tests/expr_and_series/is_finite_test.py +++ b/tests/expr_and_series/is_finite_test.py @@ -11,65 +11,60 @@ @pytest.mark.filterwarnings("ignore:invalid value encountered in cast") -def test_is_finite_expr(nw_frame_constructor: Constructor) -> None: +def test_is_finite_expr(constructor: Constructor) -> None: if any( - x in str(nw_frame_constructor) + x in str(constructor) for x in ("polars", "pyarrow_table", "duckdb", "pyspark", "ibis") ): expected = {"a": [False, False, True, None]} elif any( - x in str(nw_frame_constructor) - for x in ("pandas_constructor", "dask", "modin_constructor") + x in str(constructor) for x in ("pandas_constructor", "dask", "modin_constructor") ): expected = {"a": [False, False, True, False]} else: # pandas_nullable_constructor, pandas_pyarrow_constructor, modin_pyarrrow_constructor # Here, the 'nan' and None get mangled upon dataframe construction. expected = {"a": [None, False, True, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_finite()) assert_equal_data(result, expected) @pytest.mark.filterwarnings("ignore:invalid value encountered in cast") -def test_is_finite_series(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) or "pyarrow_table" in str( - nw_eager_constructor - ): +def test_is_finite_series(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) or "pyarrow_table" in str(constructor_eager): expected = {"a": [False, False, True, None]} elif ( - "pandas_constructor" in str(nw_eager_constructor) - or "dask" in str(nw_eager_constructor) - or "modin_constructor" in str(nw_eager_constructor) + "pandas_constructor" in str(constructor_eager) + or "dask" in str(constructor_eager) + or "modin_constructor" in str(constructor_eager) ): expected = {"a": [False, False, True, False]} else: # pandas_nullable_constructor, pandas_pyarrow_constructor, modin_pyarrrow_constructor expected = {"a": [None, False, True, None]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"a": df["a"].is_finite()} assert_equal_data(result, expected) -def test_is_finite_integer_column(nw_frame_constructor: Constructor) -> None: +def test_is_finite_integer_column(constructor: Constructor) -> None: # Test for https://github.com/narwhals-dev/narwhals/issues/3255 - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor({"a": [1, 2, 3]})) result = df.select(nw.col("a").is_finite()) assert_equal_data(result, {"a": [True, True, True]}) @pytest.mark.parametrize("data", [[1, 2, None], [1.0, 2.0, None]]) -def test_is_finite_column_with_null( - nw_frame_constructor: Constructor, data: list[float] -) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): +def test_is_finite_column_with_null(constructor: Constructor, data: list[float]) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip("need newer polars version") - df = nw.from_native(nw_frame_constructor({"a": data})) + df = nw.from_native(constructor({"a": data})) result = df.select(nw.col("a").is_finite()) expected: dict[str, list[Any]] - if nw_frame_constructor.is_non_nullable: + if constructor.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = {"a": [True, True, False]} else: diff --git a/tests/expr_and_series/is_first_distinct_test.py b/tests/expr_and_series/is_first_distinct_test.py index 6c7e4c63c1..6f0501b03c 100644 --- a/tests/expr_and_series/is_first_distinct_test.py +++ b/tests/expr_and_series/is_first_distinct_test.py @@ -14,8 +14,8 @@ data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1]} -def test_is_first_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_is_first_distinct_expr(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select(nw.all().is_first_distinct()) expected = { "a": [True, False, True, True, False], @@ -24,13 +24,13 @@ def test_is_first_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_is_first_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): +def test_is_first_distinct_expr_lazy(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("a", "b").is_first_distinct().over(order_by="i"), "i") .sort("i") @@ -43,13 +43,13 @@ def test_is_first_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_is_first_distinct_expr_lazy_w_nulls(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): +def test_is_first_distinct_expr_lazy_w_nulls(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, None, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("a", "b").is_first_distinct().over(order_by="i"), "i") .sort("i") @@ -63,19 +63,16 @@ def test_is_first_distinct_expr_lazy_w_nulls(nw_frame_constructor: Constructor) def test_is_first_distinct_expr_lazy_grouped( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any( - x in str(nw_frame_constructor) - for x in ("dask", "pandas", "pyarrow", "cudf", "modin") - ): + if any(x in str(constructor) for x in ("dask", "pandas", "pyarrow", "cudf", "modin")): request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 2, 2], "b": [1, 3, 3, 2, 3], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("b").is_first_distinct().over("a", order_by="i"), "i") .sort("i") @@ -85,8 +82,8 @@ def test_is_first_distinct_expr_lazy_grouped( assert_equal_data(result, expected) -def test_is_first_distinct_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_is_first_distinct_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.is_first_distinct() expected = {"a": [True, False, True, True, False]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_in_test.py b/tests/expr_and_series/is_in_test.py index 9aab4adbed..2ae6cabea5 100644 --- a/tests/expr_and_series/is_in_test.py +++ b/tests/expr_and_series/is_in_test.py @@ -10,32 +10,32 @@ data = {"a": [1, 4, 2, 5]} -def test_expr_is_in(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_is_in(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_in([4, 5])) expected = {"a": [False, True, False, True]} assert_equal_data(result, expected) -def test_expr_is_in_empty_list(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_is_in_empty_list(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_in([])) expected = {"a": [False, False, False, False]} assert_equal_data(result, expected) -def test_ser_is_in(nw_eager_constructor: ConstructorEager) -> None: - ser = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_ser_is_in(constructor_eager: ConstructorEager) -> None: + ser = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = {"a": ser.is_in([4, 5])} expected = {"a": [False, True, False, True]} assert_equal_data(result, expected) -def test_is_in_other(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_is_in_other(constructor: Constructor) -> None: + df_raw = constructor(data) msg = re.escape( "Narwhals `is_in` doesn't accept expressions as an argument, as opposed to " "Polars. You should provide an iterable instead." @@ -44,9 +44,9 @@ def test_is_in_other(nw_frame_constructor: Constructor) -> None: nw.from_native(df_raw).with_columns(contains=nw.col("a").is_in("sets")) -def test_filter_is_in_with_series(nw_eager_constructor: ConstructorEager) -> None: +def test_filter_is_in_with_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 4, 2, 5], "b": [1, 0, 2, 0]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.filter(nw.col("a").is_in(df["b"])) expected = {"a": [1, 2], "b": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/is_last_distinct_test.py b/tests/expr_and_series/is_last_distinct_test.py index 56268742d9..b4a96b5b9f 100644 --- a/tests/expr_and_series/is_last_distinct_test.py +++ b/tests/expr_and_series/is_last_distinct_test.py @@ -14,8 +14,8 @@ data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1]} -def test_is_last_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_is_last_distinct_expr(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select(nw.all().is_last_distinct()) expected = { "a": [False, True, False, True, True], @@ -24,12 +24,12 @@ def test_is_last_distinct_expr(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_is_last_distinct_expr_all(nw_eager_constructor: ConstructorEager) -> None: +def test_is_last_distinct_expr_all(constructor_eager: ConstructorEager) -> None: # https://github.com/narwhals-dev/narwhals/issues/2268 - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 9): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 9): pytest.skip(reason="too old version") data = {"a": [1, 1, 2, 3, 2], "b": [1, 2, 3, 2, 1], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.all().is_last_distinct().over(order_by="i")) expected = { "a": [False, True, False, True, True], @@ -39,14 +39,14 @@ def test_is_last_distinct_expr_all(nw_eager_constructor: ConstructorEager) -> No assert_equal_data(result, expected) -def test_is_last_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): +def test_is_last_distinct_expr_lazy(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, None, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("a", "b").is_last_distinct().over(order_by="i"), "i") .sort("i") @@ -60,21 +60,18 @@ def test_is_last_distinct_expr_lazy(nw_frame_constructor: Constructor) -> None: def test_is_last_distinct_expr_lazy_grouped( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any( - x in str(nw_frame_constructor) - for x in ("pandas", "pyarrow", "dask", "cudf", "modin") - ): + if any(x in str(constructor) for x in ("pandas", "pyarrow", "dask", "cudf", "modin")): # non-elementary group-by agg request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [0, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("b").is_last_distinct().over("a", order_by="i"), "i") .sort("i") @@ -85,20 +82,17 @@ def test_is_last_distinct_expr_lazy_grouped( def test_is_last_distinct_expr_lazy_grouped_nulls( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any( - x in str(nw_frame_constructor) - for x in ("pandas", "pyarrow", "dask", "cudf", "modin") - ): + if any(x in str(constructor) for x in ("pandas", "pyarrow", "dask", "cudf", "modin")): # non-elementary group-by agg request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2, 2, 2], "b": [1, 2, 2, 2, 1], "i": [None, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.select(nw.col("b").is_last_distinct().over("a", order_by="i"), "i") .sort("i") @@ -108,8 +102,8 @@ def test_is_last_distinct_expr_lazy_grouped_nulls( assert_equal_data(result, expected) -def test_is_last_distinct_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_is_last_distinct_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.is_last_distinct() expected = {"a": [False, True, False, True, True]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/is_nan_test.py b/tests/expr_and_series/is_nan_test.py index 01907aad0e..948b800a9b 100644 --- a/tests/expr_and_series/is_nan_test.py +++ b/tests/expr_and_series/is_nan_test.py @@ -8,9 +8,9 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_nan(nw_frame_constructor: Constructor) -> None: +def test_nan(constructor: Constructor) -> None: data_na = {"int": [-1, 1, None]} - df = nw.from_native(nw_frame_constructor(data_na)).with_columns( + df = nw.from_native(constructor(data_na)).with_columns( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") ** 0.5 ) result = df.select( @@ -20,14 +20,14 @@ def test_nan(nw_frame_constructor: Constructor) -> None: ) expected: dict[str, list[Any]] - if nw_frame_constructor.is_non_nullable: + if constructor.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = { "int": [False, False, True], "float": [False, False, True], "float_na": [True, False, True], } - elif "pandas" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor) and PANDAS_VERSION >= (3,): # NaN values are coerced into NA for nullable datatypes by default expected = { "int": [False, False, None], @@ -45,9 +45,9 @@ def test_nan(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_nan_series(nw_eager_constructor: ConstructorEager) -> None: +def test_nan_series(constructor_eager: ConstructorEager) -> None: data_na = {"int": [0, 1, None]} - df = nw.from_native(nw_eager_constructor(data_na), eager_only=True).with_columns( + df = nw.from_native(constructor_eager(data_na), eager_only=True).with_columns( float=nw.col("int").cast(nw.Float64), float_na=nw.col("int") / nw.col("int") ) @@ -57,14 +57,14 @@ def test_nan_series(nw_eager_constructor: ConstructorEager) -> None: "float_na": df["float_na"].is_nan(), } expected: dict[str, list[Any]] - if nw_eager_constructor.is_non_nullable: + if constructor_eager.is_non_nullable: # Null values are coerced to NaN for non-nullable datatypes expected = { "int": [False, False, True], "float": [False, False, True], "float_na": [True, False, True], } - elif "pandas" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + elif "pandas" in str(constructor_eager) and PANDAS_VERSION >= (3,): # NaN values are coerced into NA for nullable datatypes by default expected = { "int": [False, False, None], @@ -82,15 +82,13 @@ def test_nan_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_nan_non_float( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: +def test_nan_non_float(constructor: Constructor, request: pytest.FixtureRequest) -> None: pytest.importorskip("pyarrow") if ( - ("pyspark" in str(nw_frame_constructor)) - or "duckdb" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + ("pyspark" in str(constructor)) + or "duckdb" in str(constructor) + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) from pyarrow.lib import ArrowNotImplementedError @@ -98,11 +96,11 @@ def test_nan_non_float( from narwhals.exceptions import InvalidOperationError data = {"a": ["x", "y"]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) exc = ( ArrowNotImplementedError - if "pyarrow_table" in str(nw_frame_constructor) + if "pyarrow_table" in str(constructor) else InvalidOperationError ) @@ -110,18 +108,18 @@ def test_nan_non_float( df.select(nw.col("a").is_nan()).lazy().collect() -def test_nan_non_float_series(nw_eager_constructor: ConstructorEager) -> None: +def test_nan_non_float_series(constructor_eager: ConstructorEager) -> None: pytest.importorskip("pyarrow") from pyarrow.lib import ArrowNotImplementedError from narwhals.exceptions import InvalidOperationError data = {"a": ["x", "y"]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) exc = ( ArrowNotImplementedError - if "pyarrow_table" in str(nw_eager_constructor) + if "pyarrow_table" in str(constructor_eager) else InvalidOperationError ) diff --git a/tests/expr_and_series/is_null_test.py b/tests/expr_and_series/is_null_test.py index 76dfef0bda..7542af4513 100644 --- a/tests/expr_and_series/is_null_test.py +++ b/tests/expr_and_series/is_null_test.py @@ -4,19 +4,19 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_null(nw_frame_constructor: Constructor) -> None: +def test_null(constructor: Constructor) -> None: data_na = {"a": [None, 3, 2], "z": [7.0, None, None]} expected = {"a": [True, False, False], "z": [True, False, False]} - df = nw.from_native(nw_frame_constructor(data_na)) + df = nw.from_native(constructor(data_na)) result = df.select(nw.col("a").is_null(), ~nw.col("z").is_null()) assert_equal_data(result, expected) -def test_null_series(nw_eager_constructor: ConstructorEager) -> None: +def test_null_series(constructor_eager: ConstructorEager) -> None: data_na = {"a": [None, 3, 2], "z": [7.0, None, None]} expected = {"a": [True, False, False], "z": [True, False, False]} - df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) + df = nw.from_native(constructor_eager(data_na), eager_only=True) result = {"a": df["a"].is_null(), "z": ~df["z"].is_null()} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/is_unique_test.py b/tests/expr_and_series/is_unique_test.py index 14ceffa7b7..2df0518360 100644 --- a/tests/expr_and_series/is_unique_test.py +++ b/tests/expr_and_series/is_unique_test.py @@ -6,50 +6,47 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_is_unique_expr(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_is_unique_expr(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").is_unique(), "index").sort("index") expected = {"a": [False, False, True], "b": [True, True, True], "index": [0, 1, 2]} assert_equal_data(result, expected) def test_is_unique_expr_grouped( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if any( - x in str(nw_frame_constructor) - for x in ("pandas", "dask", "modin", "cudf", "pyarrow") - ): + if any(x in str(constructor) for x in ("pandas", "dask", "modin", "cudf", "pyarrow")): # non-trivial aggregation request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 4, 4], "b": [1, 1, 1, 2, 2], "index": [0, 1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").is_unique().over("b"), "index").sort("index") expected = {"a": [False, False, True, False, False], "index": [0, 1, 2, 3, 4]} assert_equal_data(result, expected) -def test_is_unique_w_nulls_expr(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_is_unique_w_nulls_expr(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [None, 1, 2], "b": [None, 2, None], "index": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").is_unique(), "index").sort("index") expected = {"a": [True, True, True], "b": [False, True, False], "index": [0, 1, 2]} assert_equal_data(result, expected) -def test_is_unique_series(nw_eager_constructor: ConstructorEager) -> None: +def test_is_unique_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2], "b": [1, 2, 3], "index": [0, 1, 2]} - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.is_unique() expected = {"a": [False, False, True]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/kurtosis_test.py b/tests/expr_and_series/kurtosis_test.py index b4e4890a67..55727445fe 100644 --- a/tests/expr_and_series/kurtosis_test.py +++ b/tests/expr_and_series/kurtosis_test.py @@ -17,9 +17,9 @@ ], ) def test_kurtosis_series( - nw_eager_constructor: ConstructorEager, data: list[float], expected: float | None + constructor_eager: ConstructorEager, data: list[float], expected: float | None ) -> None: - result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ + result = nw.from_native(constructor_eager({"a": data}), eager_only=True)[ "a" ].kurtosis() assert_equal_data({"a": [result]}, {"a": [expected]}) @@ -38,20 +38,18 @@ def test_kurtosis_series( ) @pytest.mark.filterwarnings("ignore:.*invalid value:RuntimeWarning:dask") def test_kurtosis_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, data: list[float], expected: float | None, request: pytest.FixtureRequest, ) -> None: - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): # https://github.com/ibis-project/ibis/issues/11341 request.applymarker(pytest.mark.xfail) - if "pyspark" in str(nw_frame_constructor) and int(request.node.callspec.id[-1]) == 0: + if "pyspark" in str(constructor) and int(request.node.callspec.id[-1]) == 0: # Can not infer schema from empty dataset. pytest.skip() - result = nw.from_native(nw_frame_constructor({"a": data})).select( - nw.col("a").kurtosis() - ) + result = nw.from_native(constructor({"a": data})).select(nw.col("a").kurtosis()) assert_equal_data(result, {"a": [expected]}) diff --git a/tests/expr_and_series/len_test.py b/tests/expr_and_series/len_test.py index 684cfae24c..755c389a28 100644 --- a/tests/expr_and_series/len_test.py +++ b/tests/expr_and_series/len_test.py @@ -4,10 +4,10 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_len_no_filter(nw_frame_constructor: Constructor) -> None: +def test_len_no_filter(constructor: Constructor) -> None: data = {"a": list("xyz"), "b": [1, 2, None]} expected = {"l": [3], "l2": [6], "l3": [3]} - df = nw.from_native(nw_frame_constructor(data)).select( + df = nw.from_native(constructor(data)).select( nw.col("a").len().alias("l"), (nw.col("a").len() * 2).alias("l2"), nw.col("b").len().alias("l3"), @@ -16,10 +16,10 @@ def test_len_no_filter(nw_frame_constructor: Constructor) -> None: assert_equal_data(df, expected) -def test_len_chaining(nw_eager_constructor: ConstructorEager) -> None: +def test_len_chaining(constructor_eager: ConstructorEager) -> None: data = {"a": list("xyz"), "b": [1, 2, 1]} expected = {"a1": [2], "a2": [1]} - df = nw.from_native(nw_eager_constructor(data)).select( + df = nw.from_native(constructor_eager(data)).select( nw.col("a").filter(nw.col("b") == 1).len().alias("a1"), nw.col("a").filter(nw.col("b") == 2).len().alias("a2"), ) @@ -27,14 +27,14 @@ def test_len_chaining(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(df, expected) -def test_namespace_len(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).select( +def test_namespace_len(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).select( nw.len(), a=nw.len() ) expected = {"len": [3], "a": [3]} assert_equal_data(df, expected) df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .filter(nw.col("a") < 0) .select(nw.len(), a=nw.len()) ) @@ -42,9 +42,9 @@ def test_namespace_len(nw_frame_constructor: Constructor) -> None: assert_equal_data(df, expected) -def test_len_series(nw_eager_constructor: ConstructorEager) -> None: +def test_len_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 1]} - s = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + s = nw.from_native(constructor_eager(data), eager_only=True)["a"] assert s.len() == 3 assert len(s) == 3 diff --git a/tests/expr_and_series/list/contains_test.py b/tests/expr_and_series/list/contains_test.py index edcad40861..6e56846d6e 100644 --- a/tests/expr_and_series/list/contains_test.py +++ b/tests/expr_and_series/list/contains_test.py @@ -14,28 +14,26 @@ expected = {"a": [True, None, False]} -def test_contains_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: +def test_contains_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("dask", "modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.contains(2) ) assert_equal_data(result, expected) def test_contains_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: if any( - backend in str(nw_eager_constructor) + backend in str(constructor_eager) for backend in ("modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.contains(2) assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/list/get_test.py b/tests/expr_and_series/list/get_test.py index 713f5d67b6..338ab6197a 100644 --- a/tests/expr_and_series/list/get_test.py +++ b/tests/expr_and_series/list/get_test.py @@ -13,20 +13,17 @@ @pytest.mark.parametrize(("index", "expected"), [(0, {"a": [1, None, None, None]})]) def test_get_expr( - request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, - index: int, - expected: Any, + request: pytest.FixtureRequest, constructor: Constructor, index: int, expected: Any ) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.get(index) ) @@ -36,43 +33,43 @@ def test_get_expr( @pytest.mark.parametrize(("index", "expected"), [(0, {"a": [1, None, None, None]})]) def test_get_series( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, index: int, expected: Any, ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if str(nw_eager_constructor).startswith("pandas") and "pyarrow" not in str( - nw_eager_constructor + if str(constructor_eager).startswith("pandas") and "pyarrow" not in str( + constructor_eager ): - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) msg = re.escape("Series must be of PyArrow List type to support list namespace.") with pytest.raises(TypeError, match=msg): df["a"].list.get(index) return - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.get(index) assert_equal_data({"a": result}, expected) -def test_get_expr_negative_index(nw_frame_constructor: Constructor) -> None: +def test_get_expr_negative_index(constructor: Constructor) -> None: data = {"a": [[1, 2], [None, 3], [None], None]} index = -1 - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) msg = re.escape( f"Index {index} is out of bounds: should be greater than or equal to 0." ) @@ -80,16 +77,16 @@ def test_get_expr_negative_index(nw_frame_constructor: Constructor) -> None: df.select(nw.col("a").cast(nw.List(nw.Int32())).list.get(index)) -def test_get_series_negative_index(nw_eager_constructor: ConstructorEager) -> None: +def test_get_series_negative_index(constructor_eager: ConstructorEager) -> None: data = {"a": [[1, 2], [None, 3], [None], None]} index = -1 - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) msg = re.escape( f"Index {index} is out of bounds: should be greater than or equal to 0." ) @@ -97,16 +94,16 @@ def test_get_series_negative_index(nw_eager_constructor: ConstructorEager) -> No df["a"].list.get(index) -def test_get_expr_non_int_index(nw_frame_constructor: Constructor) -> None: +def test_get_expr_non_int_index(constructor: Constructor) -> None: data = {"a": [[1, 2], [None, 3], [None], None], "index": [0, 1, 0, 0]} index = "index" - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) msg = re.escape( f"Index must be of type 'int'. Got type '{type(index).__name__}' instead." ) @@ -114,16 +111,16 @@ def test_get_expr_non_int_index(nw_frame_constructor: Constructor) -> None: df.select(nw.col("a").cast(nw.List(nw.Int32())).list.get(index)) # type: ignore[arg-type] -def test_get_series_non_int_index(nw_eager_constructor: ConstructorEager) -> None: +def test_get_series_non_int_index(constructor_eager: ConstructorEager) -> None: data = {"a": [[1, 2], [None, 3], [None], None], "index": [0, 1, 0, 0]} index = "index" - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) msg = re.escape( f"Index must be of type 'int'. Got type '{type(index).__name__}' instead." ) diff --git a/tests/expr_and_series/list/len_test.py b/tests/expr_and_series/list/len_test.py index 46598af7e4..918fda5831 100644 --- a/tests/expr_and_series/list/len_test.py +++ b/tests/expr_and_series/list/len_test.py @@ -9,18 +9,16 @@ expected = {"a": [2, 3, None, 0, 1]} -def test_len_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_len_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.len() ) @@ -28,17 +26,17 @@ def test_len_expr( def test_len_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.len() assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/list/max_test.py b/tests/expr_and_series/list/max_test.py index 60adc6f40c..646bff2244 100644 --- a/tests/expr_and_series/list/max_test.py +++ b/tests/expr_and_series/list/max_test.py @@ -14,30 +14,28 @@ expected = [4, -1, None, None, None] -def test_max_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_max_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.max() ) assert_equal_data(result, {"a": expected}) def test_max_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): + if any(backend in str(constructor_eager) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.max() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/mean_test.py b/tests/expr_and_series/list/mean_test.py index b4711bc846..9175d5b248 100644 --- a/tests/expr_and_series/list/mean_test.py +++ b/tests/expr_and_series/list/mean_test.py @@ -14,30 +14,28 @@ expected = [2.75, -1, None, None, None] -def test_mean_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_mean_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.mean() ) assert_equal_data(result, {"a": expected}) def test_mean_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): + if any(backend in str(constructor_eager) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.mean() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/median_test.py b/tests/expr_and_series/list/median_test.py index ae56095115..f0d3c615ff 100644 --- a/tests/expr_and_series/list/median_test.py +++ b/tests/expr_and_series/list/median_test.py @@ -16,30 +16,28 @@ expected_pyarrow = [2.5, -1, None, None, None, 3] -def test_median_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any( - backend in str(nw_frame_constructor) for backend in ("dask", "cudf", "ibis") - ) or ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 7)): +def test_median_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf", "ibis")) or ( + "polars" in str(constructor) and POLARS_VERSION < (0, 20, 7) + ): # ibis issue: https://github.com/ibis-project/ibis/issues/11788 request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") if ( - any(backend in str(nw_frame_constructor) for backend in ("pandas", "pyarrow")) + any(backend in str(constructor) for backend in ("pandas", "pyarrow")) and sys.version_info < (3, 10) and is_windows() ): # pragma: no cover reason = "The issue only affects old Python versions on Windows." request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.median() ) if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("pandas", "pyarrow", "pandas[pyarrow]") ): # there is a mismatch as pyarrow uses an approximate median @@ -49,27 +47,27 @@ def test_median_expr( def test_median_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("cudf",)) or ( - "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 7) + if any(backend in str(constructor_eager) for backend in ("cudf",)) or ( + "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 7) ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") if ( - any(backend in str(nw_eager_constructor) for backend in ("pandas", "pyarrow")) + any(backend in str(constructor_eager) for backend in ("pandas", "pyarrow")) and sys.version_info < (3, 10) and is_windows() ): # pragma: no cover reason = "The issue only affects old Python versions on Windows." request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.median() if any( - backend in str(nw_eager_constructor) + backend in str(constructor_eager) for backend in ("pandas", "pyarrow", "pandas[pyarrow]") ): # there is a mismatch as pyarrow uses an approximate median diff --git a/tests/expr_and_series/list/min_test.py b/tests/expr_and_series/list/min_test.py index 9995d9e553..2039f7de56 100644 --- a/tests/expr_and_series/list/min_test.py +++ b/tests/expr_and_series/list/min_test.py @@ -14,30 +14,28 @@ expected = [2, -1, None, None, None] -def test_min_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_min_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.min() ) assert_equal_data(result, {"a": expected}) def test_min_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): + if any(backend in str(constructor_eager) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.min().to_list() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/sort_test.py b/tests/expr_and_series/list/sort_test.py index 2df250bc1b..1866934a73 100644 --- a/tests/expr_and_series/list/sort_test.py +++ b/tests/expr_and_series/list/sort_test.py @@ -55,23 +55,23 @@ ) def test_sort_expr_args( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, descending: bool, # noqa: FBT001 nulls_last: bool, # noqa: FBT001 expected: list[Any], ) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "ibis" in str(nw_frame_constructor) and descending: + if "ibis" in str(constructor) and descending: # https://github.com/ibis-project/ibis/issues/11735 request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 5): pytest.skip() - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a") .cast(nw.List(nw.Int32())) .list.sort(descending=descending, nulls_last=nulls_last) @@ -90,20 +90,20 @@ def test_sort_expr_args( ) def test_sort_series_args( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, descending: bool, # noqa: FBT001 nulls_last: bool, # noqa: FBT001 expected: list[Any], ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("dask", "cudf")): + if any(backend in str(constructor_eager) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 5): pytest.skip() - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = ( df["a"] .cast(nw.List(nw.Int32())) diff --git a/tests/expr_and_series/list/sum_test.py b/tests/expr_and_series/list/sum_test.py index b96b922e07..d66266e016 100644 --- a/tests/expr_and_series/list/sum_test.py +++ b/tests/expr_and_series/list/sum_test.py @@ -14,33 +14,31 @@ expected = [11, -1, None, 0, 0] -def test_sum_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask", "cudf")): +def test_sum_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask", "cudf")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 2): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 2): reason = "version too old, duckdb 1.2 required for LambdaExpression." pytest.skip(reason=reason) - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( nw.col("a").cast(nw.List(nw.Int32())).list.sum() ) assert_equal_data(result, {"a": expected}) def test_sum_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(backend in str(nw_eager_constructor) for backend in ("cudf",)): + if any(backend in str(constructor_eager) for backend in ("cudf",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.sum() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/list/unique_test.py b/tests/expr_and_series/list/unique_test.py index d9dad08d1b..3d7c9dd039 100644 --- a/tests/expr_and_series/list/unique_test.py +++ b/tests/expr_and_series/list/unique_test.py @@ -14,18 +14,16 @@ expected = {2, 3, None} -def test_unique_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: +def test_unique_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("dask", "modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .select(nw.col("a").cast(nw.List(nw.Int32())).list.unique()) .lazy() .collect()["a"] @@ -43,14 +41,14 @@ def test_unique_expr( def test_unique_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: if any( - backend in str(nw_eager_constructor) + backend in str(constructor_eager) for backend in ("modin", "cudf", "pyarrow", "pandas") ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].cast(nw.List(nw.Int32())).list.unique().to_list() assert len(result) == 4 assert len(result[0]) == 3 diff --git a/tests/expr_and_series/lit_test.py b/tests/expr_and_series/lit_test.py index 0ba06f9960..188292c0d1 100644 --- a/tests/expr_and_series/lit_test.py +++ b/tests/expr_and_series/lit_test.py @@ -26,22 +26,22 @@ [(None, [2, 2, 2]), (nw.String, ["2", "2", "2"]), (nw.Float32, [2.0, 2.0, 2.0])], ) def test_lit( - nw_frame_constructor: Constructor, dtype: DType | None, expected_lit: list[Any] + constructor: Constructor, dtype: DType | None, expected_lit: list[Any] ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(nw.lit(2, dtype).alias("lit")) expected = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "lit": expected_lit} assert_equal_data(result, expected) -def test_lit_error(nw_frame_constructor: Constructor) -> None: +def test_lit_error(constructor: Constructor) -> None: pytest.importorskip("numpy") import numpy as np data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw).lazy() with pytest.raises( ValueError, match="numpy arrays are not supported as literal values" @@ -49,9 +49,9 @@ def test_lit_error(nw_frame_constructor: Constructor) -> None: _ = df.with_columns(nw.lit(np.array([1, 2])).alias("lit")) # pyright: ignore[reportArgumentType] -def test_lit_out_name(nw_frame_constructor: Constructor) -> None: +def test_lit_out_name(constructor: Constructor) -> None: data = {"a": [1, 3, 2]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(nw.lit(2)) expected = {"a": [1, 3, 2], "literal": [2, 2, 2]} @@ -74,20 +74,17 @@ def test_lit_out_name(nw_frame_constructor: Constructor) -> None: ], ) def test_lit_operation_in_select( - nw_frame_constructor: Constructor, - col_name: str, - expr: nw.Expr, - expected_result: list[int], + constructor: Constructor, col_name: str, expr: nw.Expr, expected_result: list[int] ) -> None: if ( - "dask" in str(nw_frame_constructor) + "dask" in str(constructor) and col_name == "right_lit_with_abs" and DASK_VERSION < (2025,) ): pytest.skip() data = {"a": [1, 3, 2]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw).lazy() result = df.select(expr.alias(col_name)) expected = {col_name: expected_result} @@ -102,13 +99,10 @@ def test_lit_operation_in_select( ], ) def test_lit_operation_in_with_columns( - nw_frame_constructor: Constructor, - col_name: str, - expr: nw.Expr, - expected_result: list[int], + constructor: Constructor, col_name: str, expr: nw.Expr, expected_result: list[int] ) -> None: data = {"a": [1, 3, 2]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw).lazy() result = df.with_columns(expr.alias(col_name)) expected = {"a": data["a"], col_name: expected_result} @@ -116,18 +110,16 @@ def test_lit_operation_in_with_columns( @pytest.mark.skipif(PANDAS_VERSION < (1, 5), reason="too old for pyarrow") -def test_date_lit( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: +def test_date_lit(constructor: Constructor, request: pytest.FixtureRequest) -> None: # https://github.com/dask/dask/issues/11637 - if "dask" in str(nw_frame_constructor) or ( + if "dask" in str(constructor) or ( # https://github.com/rapidsai/cudf/pull/18832 - "cudf" in str(nw_frame_constructor) and CUDF_VERSION >= (25, 8, 0) + "cudf" in str(constructor) and CUDF_VERSION >= (25, 8, 0) ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): pytest.importorskip("pyarrow") - df = nw.from_native(nw_frame_constructor({"a": [1]})) + df = nw.from_native(constructor({"a": [1]})) result = df.with_columns(nw.lit(date(2020, 1, 1), dtype=nw.Date)).collect_schema() if df.implementation.is_cudf(): # cudf has no date dtype @@ -171,32 +163,30 @@ def test_pyarrow_lit_string() -> None: ) def test_nested_structures( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, value: PythonLiteral, dtype: IntoDType | None, ) -> None: is_empty_dict = isinstance(value, dict) and len(value) == 0 non_pyspark_sql_like = ("duckdb", "sqlframe", "ibis") - is_non_pyspark_sql_like = any( - x in str(nw_frame_constructor) for x in non_pyspark_sql_like - ) + is_non_pyspark_sql_like = any(x in str(constructor) for x in non_pyspark_sql_like) if is_non_pyspark_sql_like and is_empty_dict: reason = "Cannot create an empty struct type for backend" request.applymarker(pytest.mark.xfail(reason=reason, raises=NotImplementedError)) # TODO(FBruzzesi): Check cudf - if any(x in str(nw_frame_constructor) for x in ("cudf", "dask")): + if any(x in str(constructor) for x in ("cudf", "dask")): reason = "Nested structures are not support for backend" request.applymarker(pytest.mark.xfail(reason=reason, raises=NotImplementedError)) - if any(x in str(nw_frame_constructor) for x in ("pandas", "modin")) and ( + if any(x in str(constructor) for x in ("pandas", "modin")) and ( PYARROW_VERSION == (0, 0, 0) or PANDAS_VERSION < (2, 0) ): # pragma: no cover reason = "Requires pyarrow and pandas 2.0+" pytest.skip(reason=reason) if ( - "polars" in str(nw_frame_constructor) + "polars" in str(constructor) and isinstance(value, dict) and POLARS_VERSION < (1, 10, 0) ): # pragma: no cover @@ -210,7 +200,7 @@ def test_nested_structures( value_ = list(value) if isinstance(value, tuple) else value expected_nested = {"nested": [value_] * size} - frame = nw.from_native(nw_frame_constructor(data)) + frame = nw.from_native(constructor(data)) result_with_cols = frame.with_columns(expr) assert_equal_data(result_with_cols, {**data, **expected_nested}) diff --git a/tests/expr_and_series/log_test.py b/tests/expr_and_series/log_test.py index ac5300d289..4157b5a4a6 100644 --- a/tests/expr_and_series/log_test.py +++ b/tests/expr_and_series/log_test.py @@ -18,16 +18,16 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") @pytest.mark.parametrize("base", [2, 10, math.e]) -def test_log_expr(nw_frame_constructor: Constructor, base: float) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_log_expr(constructor: Constructor, base: float) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").log(base=base)) assert_equal_data(result, {"a": expected[base]}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") @pytest.mark.parametrize("base", [2, 10, math.e]) -def test_log_series(nw_eager_constructor: ConstructorEager, base: float) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_log_series(constructor_eager: ConstructorEager, base: float) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.log(base=base) assert_equal_data({"a": result}, {"a": expected[base]}) diff --git a/tests/expr_and_series/map_batches_test.py b/tests/expr_and_series/map_batches_test.py index 8798131cba..d6f8cc8b32 100644 --- a/tests/expr_and_series/map_batches_test.py +++ b/tests/expr_and_series/map_batches_test.py @@ -20,8 +20,8 @@ data = {"a": [1, 2, 3], "b": [4, 5, 6], "z": [7.0, 8.0, 9.0]} -def test_map_batches_expr_compliant(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_map_batches_expr_compliant(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) expected = df.select(nw.col("a", "b").map_batches(lambda s: s + 1).name.suffix("1")) assert_equal_data(expected, {"a1": [2, 3, 4], "b1": [5, 6, 7]}) @@ -31,9 +31,9 @@ def test_map_batches_expr_compliant(nw_eager_constructor: ConstructorEager) -> N [(1, nw.Int64()), ("foo", nw.String()), ([1, 2], nw.List(nw.Int64()))], ) def test_map_batches_expr_scalar( - nw_eager_constructor: ConstructorEager, value: Any, dtype: DType + constructor_eager: ConstructorEager, value: Any, dtype: DType ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) if dtype.is_nested() and df.implementation.is_pandas_like(): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "pandas is too old for nested types" @@ -48,8 +48,8 @@ def test_map_batches_expr_scalar( assert_equal_data(expected, {"a": [value], "b": [value]}) -def test_map_batches_expr_numpy_array(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_map_batches_expr_numpy_array(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) expected = df.select( nw.col("a") .map_batches(lambda s: s.to_numpy() + 1, return_dtype=nw.Float64()) @@ -58,8 +58,8 @@ def test_map_batches_expr_numpy_array(nw_eager_constructor: ConstructorEager) -> assert_equal_data(expected, {"a": [9.0]}) -def test_map_batches_expr_numpy_scalar(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_map_batches_expr_numpy_scalar(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) expected = df.select( nw.all().map_batches(lambda s: s.to_numpy().argmax(), returns_scalar=True) @@ -67,19 +67,19 @@ def test_map_batches_expr_numpy_scalar(nw_eager_constructor: ConstructorEager) - assert_equal_data(expected, {"a": [2], "b": [2], "z": [2]}) -def test_map_batches_expr_names(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_map_batches_expr_names(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) expected = nw.from_native(df.select(nw.all().map_batches(lambda x: x.to_numpy()))) assert_equal_data(expected, {"a": [1, 2, 3], "b": [4, 5, 6], "z": [7.0, 8.0, 9.0]}) def test_map_batches_exception( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 32, 3): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 32, 3): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) msg = ( r"`map(?:_batches)?` with `returns_scalar=False` must return a Series; found " r"'numpy\.int(?:32|64)'\." diff --git a/tests/expr_and_series/max_horizontal_test.py b/tests/expr_and_series/max_horizontal_test.py index f435ce5611..cc0bddfb1a 100644 --- a/tests/expr_and_series/max_horizontal_test.py +++ b/tests/expr_and_series/max_horizontal_test.py @@ -10,16 +10,16 @@ @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_maxh(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_maxh(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(horizontal_max=nw.max_horizontal("a", nw.col("b"), "z")) expected = {"horizontal_max": expected_values} assert_equal_data(result, expected) @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_maxh_all(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_maxh_all(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.max_horizontal(nw.all()), c=nw.max_horizontal(nw.all())) expected = {"a": expected_values, "c": expected_values} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/max_test.py b/tests/expr_and_series/max_test.py index ce58eddc2b..eb359121c6 100644 --- a/tests/expr_and_series/max_test.py +++ b/tests/expr_and_series/max_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").max(), nw.max("a", "b", "z")]) -def test_expr_max_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_max_expr(constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(constructor(data)) result = df.select(expr) expected = {"a": [3], "b": [6], "z": [9.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_max_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None @pytest.mark.parametrize(("col", "expected"), [("a", 3), ("b", 6), ("z", 9.0)]) def test_expr_max_series( - nw_eager_constructor: ConstructorEager, col: str, expected: float + constructor_eager: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.max() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/mean_horizontal_test.py b/tests/expr_and_series/mean_horizontal_test.py index a87ed4df99..bc5bc12fa6 100644 --- a/tests/expr_and_series/mean_horizontal_test.py +++ b/tests/expr_and_series/mean_horizontal_test.py @@ -6,29 +6,29 @@ from tests.utils import Constructor, assert_equal_data -def test_meanh(nw_frame_constructor: Constructor) -> None: +def test_meanh(constructor: Constructor) -> None: data = {"a": [1, 3, None, None], "b": [4, None, 6, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(horizontal_mean=nw.mean_horizontal(nw.col("a"), nw.col("b"))) expected = {"horizontal_mean": [2.5, 3.0, 6.0, None]} assert_equal_data(result, expected) def test_meanh_with_literal( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, None, None], "b": [4, None, 6, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(horizontal_mean=nw.mean_horizontal(nw.lit(1), "a", nw.col("b"))) expected = {"horizontal_mean": [2.0, 2.0, 3.5, 1.0]} assert_equal_data(result, expected) -def test_meanh_all(nw_frame_constructor: Constructor) -> None: +def test_meanh_all(constructor: Constructor) -> None: data = {"a": [2, 4, 6], "b": [10, 20, 30]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.mean_horizontal(nw.all())) expected = {"a": [6, 12, 18]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/mean_test.py b/tests/expr_and_series/mean_test.py index a0b19583a3..39a97bd53a 100644 --- a/tests/expr_and_series/mean_test.py +++ b/tests/expr_and_series/mean_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").mean(), nw.mean("a", "b", "z")]) -def test_expr_mean_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_mean_expr(constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(constructor(data)) result = df.select(expr) expected = {"a": [2.0], "b": [5.0], "z": [8.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_mean_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> Non @pytest.mark.parametrize(("col", "expected"), [("a", 2.0), ("b", 5.0), ("z", 8.0)]) def test_expr_mean_series( - nw_eager_constructor: ConstructorEager, col: str, expected: float + constructor_eager: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.mean() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/median_test.py b/tests/expr_and_series/median_test.py index 356397d640..b01350586a 100644 --- a/tests/expr_and_series/median_test.py +++ b/tests/expr_and_series/median_test.py @@ -20,11 +20,11 @@ "expr", [nw.col("a", "b", "z").median(), nw.median("a", "b", "z")] ) def test_median_expr( - nw_frame_constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest + constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest ) -> None: - if "dask_lazy_p2" in str(nw_frame_constructor): + if "dask_lazy_p2" in str(constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(expr) expected = {"a": [3.0], "b": [5.0], "z": [8.0]} assert_equal_data(result, expected) @@ -32,25 +32,25 @@ def test_median_expr( @pytest.mark.parametrize(("col", "expected"), [("a", 3.0), ("b", 5.0), ("z", 8.0)]) def test_median_series( - nw_eager_constructor: ConstructorEager, col: str, expected: float + constructor_eager: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.median() assert_equal_data({col: [result]}, {col: [expected]}) @pytest.mark.parametrize("expr", [nw.col("s").median(), nw.median("s")]) def test_median_expr_raises_on_str( - nw_frame_constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest + constructor: Constructor, expr: nw.Expr, request: pytest.FixtureRequest ) -> None: if ( - ("pyspark" in str(nw_frame_constructor)) - or "duckdb" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + ("pyspark" in str(constructor)) + or "duckdb" in str(constructor) + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) if isinstance(df, nw.LazyFrame): with pytest.raises( InvalidOperationError, match="`median` operation not supported" @@ -65,9 +65,9 @@ def test_median_expr_raises_on_str( @pytest.mark.parametrize(("col"), [("s")]) def test_median_series_raises_on_str( - nw_eager_constructor: ConstructorEager, col: str + constructor_eager: ConstructorEager, col: str ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] with pytest.raises( InvalidOperationError, match=re.escape("`median` operation not supported for non-numeric input type."), diff --git a/tests/expr_and_series/min_horizontal_test.py b/tests/expr_and_series/min_horizontal_test.py index f91bf1338f..df9ff31feb 100644 --- a/tests/expr_and_series/min_horizontal_test.py +++ b/tests/expr_and_series/min_horizontal_test.py @@ -10,16 +10,16 @@ @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_minh(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_minh(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(horizontal_min=nw.min_horizontal("a", nw.col("b"), "z")) expected = {"horizontal_min": expected_values} assert_equal_data(result, expected) @pytest.mark.filterwarnings(r"ignore:.*All-NaN slice encountered:RuntimeWarning") -def test_minh_all(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_minh_all(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.min_horizontal(nw.all()), c=nw.min_horizontal(nw.all())) expected = {"a": expected_values, "c": expected_values} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/min_test.py b/tests/expr_and_series/min_test.py index c8f0409da5..842e70c166 100644 --- a/tests/expr_and_series/min_test.py +++ b/tests/expr_and_series/min_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").min(), nw.min("a", "b", "z")]) -def test_expr_min_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_min_expr(constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(constructor(data)) result = df.select(expr) expected = {"a": [1], "b": [4], "z": [7.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_min_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None @pytest.mark.parametrize(("col", "expected"), [("a", 1), ("b", 4), ("z", 7.0)]) def test_expr_min_series( - nw_eager_constructor: ConstructorEager, col: str, expected: float + constructor_eager: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.min() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/mode_test.py b/tests/expr_and_series/mode_test.py index 2df3dcf900..a17de7bd17 100644 --- a/tests/expr_and_series/mode_test.py +++ b/tests/expr_and_series/mode_test.py @@ -19,22 +19,22 @@ } -def test_mode_single_expr_keep_all(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_mode_single_expr_keep_all(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").mode(keep="all")).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series_keep_all(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_mode_series_keep_all(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.mode(keep="all").sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_series_keep_any(nw_eager_constructor: ConstructorEager) -> None: - frame = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_mode_series_keep_any(constructor_eager: ConstructorEager) -> None: + frame = nw.from_native(constructor_eager(data), eager_only=True) result_a = frame["a"].mode(keep="any") assert result_a in {1, 2} @@ -42,16 +42,16 @@ def test_mode_series_keep_any(nw_eager_constructor: ConstructorEager) -> None: assert result_b == 3 -def test_mode_different_lengths_keep_all(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths_keep_all(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) with pytest.raises(ShapeError): df.select(nw.col("a", "b").mode(keep="all")) -def test_mode_expr_keep_any(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_mode_expr_keep_any(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").mode(keep="any")).lazy().collect() try: @@ -62,8 +62,8 @@ def test_mode_expr_keep_any(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_mode_expr_keep_all_lazy(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_mode_expr_keep_all_lazy(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) impl = df.implementation not_implemented = { nw.Implementation.DUCKDB, @@ -85,9 +85,9 @@ def test_mode_expr_keep_all_lazy(nw_frame_constructor: Constructor) -> None: def test_mode_group_by_unimodal( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - df = nw.from_native(nw_frame_constructor(data_group)) + df = nw.from_native(constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): @@ -115,13 +115,13 @@ def test_mode_group_by_unimodal( ], ) def test_mode_group_by_multimodal( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, mode_col: str, expected_opt_1: list[Any], expected_opt_2: list[Any], ) -> None: - df = nw.from_native(nw_frame_constructor(data_group)) + df = nw.from_native(constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): @@ -156,11 +156,11 @@ def test_mode_group_by_multimodal( ], ) def test_mode_group_by_multiple_cols( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, mode_expr: nw.Expr | list[nw.Expr], ) -> None: - df = nw.from_native(nw_frame_constructor(data_group)) + df = nw.from_native(constructor(data_group)) impl = df.implementation if impl.is_dask() or impl.is_pyarrow(): diff --git a/tests/expr_and_series/n_unique_test.py b/tests/expr_and_series/n_unique_test.py index 8ac6ae25ea..e9af1f0154 100644 --- a/tests/expr_and_series/n_unique_test.py +++ b/tests/expr_and_series/n_unique_test.py @@ -8,35 +8,31 @@ data = {"a": [1.0, None, None, 3.0], "b": [1.0, None, 4.0, 5.0]} -def test_n_unique(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_n_unique(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.all().n_unique()) expected = {"a": [3], "b": [4]} assert_equal_data(result, expected) -def test_n_unique_over( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_n_unique_over(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/10550 request.applymarker(pytest.mark.xfail) - if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( - nw_frame_constructor - ): + if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): # "Distinct window functions are not supported" request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): reason = "NotImplementedError: Passing kwargs to func is currently not supported." request.applymarker(pytest.mark.xfail(reason=reason)) data = {"a": [1, None, None, 1, 2, 2, 2, None, 3], "b": [1, 1, 1, 1, 1, 1, 1, 2, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns( nw.all().n_unique(), a_over_b=nw.col("a").n_unique().over("b") ).sort("a_over_b") @@ -44,8 +40,8 @@ def test_n_unique_over( assert_equal_data(result, expected) -def test_n_unique_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_n_unique_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = {"a": [3], "b": [4]} result_series = {"a": [df["a"].n_unique()], "b": [df["b"].n_unique()]} assert_equal_data(result_series, expected) diff --git a/tests/expr_and_series/name/keep_test.py b/tests/expr_and_series/name/keep_test.py index aaeb68de44..e4a3ba17f6 100644 --- a/tests/expr_and_series/name/keep_test.py +++ b/tests/expr_and_series/name/keep_test.py @@ -6,22 +6,22 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_keep(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_keep(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.keep()) expected = {k: [e * 2 for e in v] for k, v in data.items()} assert_equal_data(result, expected) -def test_keep_after_alias(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_keep_after_alias(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.keep()) expected = {"foo": data["foo"]} assert_equal_data(result, expected) -def test_keep_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_keep_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select("foo").select(nw.all().alias("fdfsad").name.keep()) expected = {"foo": [1, 2, 3]} diff --git a/tests/expr_and_series/name/map_test.py b/tests/expr_and_series/name/map_test.py index 2a7e420433..eb4b2bc22b 100644 --- a/tests/expr_and_series/name/map_test.py +++ b/tests/expr_and_series/name/map_test.py @@ -12,24 +12,24 @@ def map_func(s: str | None) -> str: return str(s)[::-1].lower() -def test_map(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_map(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.map(function=map_func)) expected = {"oof": [2, 4, 6], "rab": [8, 10, 12]} assert_equal_data(result, expected) -def test_map_after_alias(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_map_after_alias(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.map(function=map_func)) expected = {"oof_rof_saila": data["foo"]} assert_equal_data(result, expected) -def test_map_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_map_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.map(function=map_func)) expected = {"oof": [1, 2, 3], "rab": [4, 5, 6]} diff --git a/tests/expr_and_series/name/prefix_test.py b/tests/expr_and_series/name/prefix_test.py index d775eb681c..a639455823 100644 --- a/tests/expr_and_series/name/prefix_test.py +++ b/tests/expr_and_series/name/prefix_test.py @@ -9,24 +9,24 @@ prefix = "with_prefix_" -def test_prefix(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_prefix(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.prefix(prefix)) expected = {"with_prefix_foo": [2, 4, 6], "with_prefix_BAR": [8, 10, 12]} assert_equal_data(result, expected) -def test_suffix_after_alias(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_suffix_after_alias(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.prefix(prefix)) expected = {"with_prefix_alias_for_foo": [1, 2, 3]} assert_equal_data(result, expected) -def test_prefix_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_prefix_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.prefix(prefix)) expected = {"with_prefix_foo": [1, 2, 3], "with_prefix_BAR": [4, 5, 6]} diff --git a/tests/expr_and_series/name/suffix_test.py b/tests/expr_and_series/name/suffix_test.py index 67b26bff6d..437d93e05a 100644 --- a/tests/expr_and_series/name/suffix_test.py +++ b/tests/expr_and_series/name/suffix_test.py @@ -9,17 +9,17 @@ suffix = "_with_suffix" -def test_suffix(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_suffix(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.suffix(suffix)) expected = {"foo_with_suffix": [2, 4, 6], "BAR_with_suffix": [8, 10, 12]} assert_equal_data(result, expected) -def test_suffix_after_alias(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_suffix_after_alias(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.suffix(suffix)) expected = {"alias_for_foo_with_suffix": [1, 2, 3]} assert_equal_data(result, expected) @@ -30,8 +30,8 @@ def test_suffix_after_alias(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_suffix_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_suffix_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.suffix(suffix)) expected = {"foo_with_suffix": [1, 2, 3], "BAR_with_suffix": [4, 5, 6]} diff --git a/tests/expr_and_series/name/to_lowercase_test.py b/tests/expr_and_series/name/to_lowercase_test.py index b586a34e06..41a88a4f9c 100644 --- a/tests/expr_and_series/name/to_lowercase_test.py +++ b/tests/expr_and_series/name/to_lowercase_test.py @@ -8,24 +8,24 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_to_lowercase(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_to_lowercase(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.to_lowercase()) expected = {"foo": [2, 4, 6], "bar": [8, 10, 12]} assert_equal_data(result, expected) -def test_to_lowercase_after_alias(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_to_lowercase_after_alias(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select((nw.col("BAR")).alias("ALIAS_FOR_BAR").name.to_lowercase()) expected = {"alias_for_bar": [4, 5, 6]} assert_equal_data(result, expected) -def test_to_lowercase_raise_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_to_lowercase_raise_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.to_lowercase()) expected = {"foo": [1, 2, 3], "bar": [4, 5, 6]} diff --git a/tests/expr_and_series/name/to_uppercase_test.py b/tests/expr_and_series/name/to_uppercase_test.py index 441ddcc992..9204ac86b5 100644 --- a/tests/expr_and_series/name/to_uppercase_test.py +++ b/tests/expr_and_series/name/to_uppercase_test.py @@ -8,24 +8,24 @@ data = {"foo": [1, 2, 3], "BAR": [4, 5, 6]} -def test_to_uppercase(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_to_uppercase(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo", "BAR") * 2).name.to_uppercase()) expected = {"FOO": [2, 4, 6], "BAR": [8, 10, 12]} assert_equal_data(result, expected) -def test_to_uppercase_after_alias(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_to_uppercase_after_alias(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/23765") - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select((nw.col("foo")).alias("alias_for_foo").name.to_uppercase()) expected = {"ALIAS_FOR_FOO": [1, 2, 3]} assert_equal_data(result, expected) -def test_to_uppercase_anonymous(nw_frame_constructor: Constructor) -> None: - df_raw = nw_frame_constructor(data) +def test_to_uppercase_anonymous(constructor: Constructor) -> None: + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.select(nw.all().name.to_uppercase()) expected = {"FOO": [1, 2, 3], "BAR": [4, 5, 6]} diff --git a/tests/expr_and_series/nth_test.py b/tests/expr_and_series/nth_test.py index 0ec1fe52c7..86f9bfe2eb 100644 --- a/tests/expr_and_series/nth_test.py +++ b/tests/expr_and_series/nth_test.py @@ -20,13 +20,11 @@ ], ) def test_nth( - nw_frame_constructor: Constructor, - idx: int | list[int], - expected: dict[str, list[int]], + constructor: Constructor, idx: int | list[int], expected: dict[str, list[int]] ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0, 0): + if "polars" in str(constructor) and POLARS_VERSION < (1, 0, 0): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.nth(idx)) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/null_count_test.py b/tests/expr_and_series/null_count_test.py index 6e554ce00e..6efef0ada1 100644 --- a/tests/expr_and_series/null_count_test.py +++ b/tests/expr_and_series/null_count_test.py @@ -6,15 +6,15 @@ data = {"a": [1.0, None, None, 3.0], "b": [1.0, None, 4.0, 5.0]} -def test_null_count_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_null_count_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a", "b").null_count()) expected = {"a": [2], "b": [1]} assert_equal_data(result, expected) -def test_null_count_series(nw_eager_constructor: ConstructorEager) -> None: +def test_null_count_series(constructor_eager: ConstructorEager) -> None: data = [1, 2, None] - series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] result = series.null_count() assert result == 1 diff --git a/tests/expr_and_series/operators_test.py b/tests/expr_and_series/operators_test.py index d7fa63d827..f505c8f972 100644 --- a/tests/expr_and_series/operators_test.py +++ b/tests/expr_and_series/operators_test.py @@ -18,10 +18,10 @@ ], ) def test_comparand_operators_scalar_expr( - nw_frame_constructor: Constructor, operator: str, expected: list[bool] + constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a"), operator)(1)) assert_equal_data(result, {"a": expected}) @@ -38,10 +38,10 @@ def test_comparand_operators_scalar_expr( ], ) def test_comparand_operators_expr( - nw_frame_constructor: Constructor, operator: str, expected: list[bool] + constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 1], "b": [0, 0, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a"), operator)(nw.col("b"))) assert_equal_data(result, {"a": expected}) @@ -51,34 +51,34 @@ def test_comparand_operators_expr( [("__and__", [True, False, False, False]), ("__or__", [True, True, True, False])], ) def test_logic_operators_expr( - nw_frame_constructor: Constructor, operator: str, expected: list[bool] + constructor: Constructor, operator: str, expected: list[bool] ) -> None: data = {"a": [True, True, False, False], "b": [True, False, True, False]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(getattr(nw.col("a"), operator)(nw.col("b"))) assert_equal_data(result, {"a": expected}) def test_logic_operators_expr_kleene( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/19171 request.applymarker(pytest.mark.xfail) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # Dask infers `[True, None, None, None]` as `object` dtype, and then `__or__` fails. request.applymarker(pytest.mark.xfail) data = {"a": [True, True, False, None], "b": [True, None, None, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a") | (nw.col("b"))) - if any(x in str(nw_frame_constructor) for x in ("pandas_constructor",)): + if any(x in str(constructor) for x in ("pandas_constructor",)): expected: list[bool | None] = [True, True, False, False] else: expected = [True, True, None, None] assert_equal_data(result, {"a": expected}) result = df.select(nw.col("a") & (nw.col("b"))) - if any(x in str(nw_frame_constructor) for x in ("pandas_constructor",)): + if any(x in str(constructor) for x in ("pandas_constructor",)): expected = [True, False, False, False] else: expected = [True, None, False, None] @@ -95,19 +95,19 @@ def test_logic_operators_expr_kleene( ], ) def test_logic_operators_expr_scalar( - nw_frame_constructor: Constructor, + constructor: Constructor, operator: str, expected: list[bool], request: pytest.FixtureRequest, ) -> None: if ( - "dask" in str(nw_frame_constructor) + "dask" in str(constructor) and DASK_VERSION < (2024, 10) and operator in {"__rand__", "__ror__"} ): request.applymarker(pytest.mark.xfail) data = {"a": [True, True, False, False]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(a=getattr(nw.col("a"), operator)(False)) assert_equal_data(result, {"a": expected}) @@ -125,10 +125,10 @@ def test_logic_operators_expr_scalar( ], ) def test_comparand_operators_scalar_series( - nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] + constructor_eager: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 2]} - s = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + s = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = {"a": (getattr(s, operator)(1))} assert_equal_data(result, {"a": expected}) @@ -145,10 +145,10 @@ def test_comparand_operators_scalar_series( ], ) def test_comparand_operators_series( - nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] + constructor_eager: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [0, 1, 1], "b": [0, 0, 2]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) series, other = df["a"], df["b"] result = {"a": getattr(series, operator)(other)} assert_equal_data(result, {"a": expected}) @@ -164,10 +164,10 @@ def test_comparand_operators_series( ], ) def test_logic_operators_series( - nw_eager_constructor: ConstructorEager, operator: str, expected: list[bool] + constructor_eager: ConstructorEager, operator: str, expected: list[bool] ) -> None: data = {"a": [True, True, False, False], "b": [True, False, True, False]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) series, other = df["a"], df["b"] result = {"a": getattr(series, operator)(other)} assert_equal_data(result, {"a": expected}) diff --git a/tests/expr_and_series/order_dependent_lazy_test.py b/tests/expr_and_series/order_dependent_lazy_test.py index 532b2ab8a7..70bd234828 100644 --- a/tests/expr_and_series/order_dependent_lazy_test.py +++ b/tests/expr_and_series/order_dependent_lazy_test.py @@ -11,8 +11,8 @@ from tests.utils import Constructor -def test_order_dependent_raises_in_lazy(nw_frame_constructor: Constructor) -> None: - lf = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})).lazy() +def test_order_dependent_raises_in_lazy(constructor: Constructor) -> None: + lf = nw.from_native(constructor({"a": [1, 2, 3]})).lazy() with pytest.raises(InvalidOperationError, match="Order-dependent expressions"): lf.select(nw.col("a").diff()) with pytest.raises(InvalidOperationError, match="Order-dependent expressions"): diff --git a/tests/expr_and_series/over_pushdown_test.py b/tests/expr_and_series/over_pushdown_test.py index 9af8890085..8a8c9795d0 100644 --- a/tests/expr_and_series/over_pushdown_test.py +++ b/tests/expr_and_series/over_pushdown_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_over_pushdown(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_over_pushdown(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, -4, 5, 6, -1], "b": [1, 1, 1, 2, 2, 2], "i": list(range(6))} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( "i", a=nw.col("a").sum().abs().over("b"), diff --git a/tests/expr_and_series/over_test.py b/tests/expr_and_series/over_test.py index 8635bd1027..7fbb8f0f9f 100644 --- a/tests/expr_and_series/over_test.py +++ b/tests/expr_and_series/over_test.py @@ -30,11 +30,11 @@ } -def test_over_single(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_over_single(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -49,16 +49,14 @@ def test_over_single(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_over_std_var( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if "cudf" in str(nw_frame_constructor): +def test_over_std_var(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if "cudf" in str(constructor): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -85,10 +83,10 @@ def test_over_std_var( assert_equal_data(result, expected) -def test_over_multiple(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_over_multiple(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -102,17 +100,17 @@ def test_over_multiple(nw_frame_constructor: Constructor) -> None: def test_over_cumsum( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_cum)) + df = nw.from_native(constructor_eager(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -130,15 +128,15 @@ def test_over_cumsum( def test_over_cumcount( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_cum)) + df = nw.from_native(constructor_eager(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -156,16 +154,16 @@ def test_over_cumcount( def test_over_cummax( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_cum)) + df = nw.from_native(constructor_eager(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -182,17 +180,17 @@ def test_over_cummax( def test_over_cummin( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_cum)) + df = nw.from_native(constructor_eager(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -210,17 +208,17 @@ def test_over_cummin( def test_over_cumprod( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_cum)) + df = nw.from_native(constructor_eager(data_cum)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, None, 5, 3], @@ -238,12 +236,12 @@ def test_over_cumprod( def test_over_anonymous_cumulative( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(constructor_eager({"": [1, 1, 2], "b": [4, 5, 6]})) context = ( pytest.raises(NotImplementedError) if df.implementation.is_pyarrow() @@ -268,15 +266,15 @@ def test_over_anonymous_cumulative( def test_over_anonymous_reduction( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # probably bugged request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) context = ( pytest.raises(NotImplementedError) if df.implementation.is_pyarrow() @@ -317,15 +315,15 @@ def test_over_unsupported_dask() -> None: def test_over_shift( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -337,15 +335,15 @@ def test_over_shift( def test_over_diff( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) expected = { "a": ["a", "a", "b", "b", "b"], "b": [1, 2, 3, 5, 3], @@ -367,33 +365,33 @@ def test_over_diff( ], ) def test_over_cum_reverse( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, attr: str, expected_b: list[object], ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) if ( - "pandas_nullable" in str(nw_eager_constructor) + "pandas_nullable" in str(constructor_eager) and attr in {"cum_max", "cum_min"} and PANDAS_VERSION < (3, 0) ): # TODO(FBruzzesi): convert to pytest.skip() if the fix does not make it into # `pandas=2.3.4`. Otherwise update version boundary request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - df = nw_eager_constructor({"a": [1, 1, 2, 2, 2], "b": [4, 5, 7, None, 9]}) + df = constructor_eager({"a": [1, 1, 2, 2, 2], "b": [4, 5, 7, None, 9]}) expr = getattr(nw.col("b"), attr)(reverse=True) result = nw.from_native(df).with_columns(expr.over("a")) expected = {"a": [1, 1, 2, 2, 2], "b": expected_b} assert_equal_data(result, expected) -def test_over_raise_len_change(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_over_raise_len_change(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): nw.from_native(df).select(nw.col("b").drop_nulls().over("a")) @@ -415,15 +413,15 @@ def test_unsupported_over() -> None: def test_over_without_partition_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): # windows not yet supported request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) + df = nw.from_native(constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) result = ( df.with_columns(b=nw.col("a").abs().cum_sum().over(order_by="i")) .sort("i") @@ -434,12 +432,12 @@ def test_over_without_partition_by( def test_aggregation_over_without_partition_by( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw.from_native(nw_eager_constructor({"a": [1, -1, 2], "i": [0, 2, 1]})) + df = nw.from_native(constructor_eager({"a": [1, -1, 2], "i": [0, 2, 1]})) result = ( df.with_columns(b=nw.col("a").diff().sum().over(order_by="i")) .sort("i") @@ -449,38 +447,34 @@ def test_aggregation_over_without_partition_by( assert_equal_data(result, expected) -def test_len_over_2369( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_len_over_2369(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 5): + if "pandas" in str(constructor) and PANDAS_VERSION < (1, 5): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("modin", "cudf")): + if any(x in str(constructor) for x in ("modin", "cudf")): # https://github.com/modin-project/modin/issues/7508 # https://github.com/rapidsai/cudf/issues/18491 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 4], "b": ["x", "x", "y"]})) + df = nw.from_native(constructor({"a": [1, 2, 4], "b": ["x", "x", "y"]})) result = df.with_columns(a_len_per_group=nw.len().over("b")).sort("a") expected = {"a": [1, 2, 4], "b": ["x", "x", "y"], "a_len_per_group": [2, 2, 1]} assert_equal_data(result, expected) -def test_over_quantile( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "pyspark", "cudf")): +def test_over_quantile(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if any(x in str(constructor) for x in ("pyarrow_table", "pyspark", "cudf")): # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3, 4, 5, 6], "b": ["x", "x", "x", "y", "y", "y"]} quantile_expr = nw.col("a").quantile(quantile=0.5, interpolation="linear") - native_frame = nw_frame_constructor(data) + native_frame = constructor(data) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): native_frame = native_frame.repartition(npartitions=1) # type: ignore[union-attr] result = ( @@ -500,19 +494,19 @@ def test_over_quantile( def test_over_ewm_mean( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin", "cudf")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin", "cudf")): # not implemented request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (1, 2): + if "pandas" in str(constructor_eager) and PANDAS_VERSION < (1, 2): request.applymarker(pytest.mark.xfail(reason="too old, not implemented")) data = {"a": [0.0, 1.0, 3.0, 5.0, 7.0, 7.5], "b": [1, 1, 1, 2, 2, 2]} ewm_expr = nw.col("a").ewm_mean(com=1) result = ( - nw.from_native(nw_eager_constructor(data)) + nw.from_native(constructor_eager(data)) .with_columns(ewm_over_b=ewm_expr.over("b"), ewm_global=ewm_expr) .sort("a") ) @@ -533,13 +527,13 @@ def test_over_ewm_mean( ], ) def test_over_with_nulls_in_partition( - nw_frame_constructor: Constructor, + constructor: Constructor, partition: list[str], expected_min: list[int], expected_max: list[int], ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3300 - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { "a": [1, 1, None, 3, 3], @@ -547,7 +541,7 @@ def test_over_with_nulls_in_partition( "c": [1, 1, None, 3, 4], # second group with nulls "d": [1, 1, 2, 2, 3], # second group without nulls } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) expected = {"b": [1, 3, 4, 5, 6], "bmin": expected_min, "bmax": expected_max} result = df.select( "b", @@ -576,7 +570,7 @@ def test_over_with_nulls_in_partition( ) def test_over_when_then_aggregation_partition_by( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, expr: nw.Expr, expected_c: list[float], ) -> None: @@ -584,13 +578,13 @@ def test_over_when_then_aggregation_partition_by( # tests/imputers/test_ModeImputer.py::TestFit::test_learnt_values_tied_weighted[input_col1-weight_col1-b-False-pandas] # tubular commit: b2ca639aa26e620271b87d43de826006765b1f48 # https://github.com/narwhals-dev/narwhals/issues/3300 - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): request.applymarker(pytest.mark.xfail(reason="Value mismatch")) data = {"a": [1, 1, None, 3, 3], "b": [1, 3, 4, 5, 6], "g": [1, 1, 2, 3, 3]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select("a", "b", c=expr).sort("b") expected = {"a": [1, 1, None, 3, 3], "b": [1, 3, 4, 5, 6], "c": expected_c} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/pipe_test.py b/tests/expr_and_series/pipe_test.py index 4d7821faab..d32743e1ea 100644 --- a/tests/expr_and_series/pipe_test.py +++ b/tests/expr_and_series/pipe_test.py @@ -7,13 +7,13 @@ expected = [4, 16, 36, 64] -def test_pipe_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(input_list)) +def test_pipe_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(input_list)) e = df.select(nw.col("a").pipe(lambda x: x**2)) assert_equal_data(e, {"a": expected}) -def test_pipe_series(nw_eager_constructor: ConstructorEager) -> None: - s = nw.from_native(nw_eager_constructor(input_list), eager_only=True)["a"] +def test_pipe_series(constructor_eager: ConstructorEager) -> None: + s = nw.from_native(constructor_eager(input_list), eager_only=True)["a"] result = s.pipe(lambda x: x**2) assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/quantile_test.py b/tests/expr_and_series/quantile_test.py index 830a65218d..39489db89d 100644 --- a/tests/expr_and_series/quantile_test.py +++ b/tests/expr_and_series/quantile_test.py @@ -22,20 +22,20 @@ ) @pytest.mark.filterwarnings("ignore:the `interpolation=` argument to percentile") def test_quantile_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, interpolation: Literal["nearest", "higher", "lower", "midpoint", "linear"], expected: dict[str, list[float]], request: pytest.FixtureRequest, ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("dask", "duckdb", "ibis")) + any(x in str(constructor) for x in ("dask", "duckdb", "ibis")) and interpolation != "linear" - ) or "pyspark" in str(nw_frame_constructor): + ) or "pyspark" in str(constructor): request.applymarker(pytest.mark.xfail) q = 0.3 data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) msg = re.escape( @@ -43,7 +43,7 @@ def test_quantile_expr( ) context = ( pytest.raises(NotImplementedError, match=msg) - if "dask_lazy_p2" in str(nw_frame_constructor) + if "dask_lazy_p2" in str(constructor) else does_not_raise() ) @@ -64,14 +64,14 @@ def test_quantile_expr( ) @pytest.mark.filterwarnings("ignore:the `interpolation=` argument to percentile") def test_quantile_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, interpolation: Literal["nearest", "higher", "lower", "midpoint", "linear"], expected: float, ) -> None: q = 0.3 - series = nw.from_native( - nw_eager_constructor({"a": [7.0, 8.0, 9.0]}), eager_only=True - )["a"].alias("a") + series = nw.from_native(constructor_eager({"a": [7.0, 8.0, 9.0]}), eager_only=True)[ + "a" + ].alias("a") result = series.quantile(quantile=q, interpolation=interpolation) assert_equal_data({"a": [result]}, {"a": [expected]}) diff --git a/tests/expr_and_series/rank_test.py b/tests/expr_and_series/rank_test.py index f726848ccc..fb50fdeb59 100644 --- a/tests/expr_and_series/rank_test.py +++ b/tests/expr_and_series/rank_test.py @@ -61,18 +61,18 @@ @pytest.mark.parametrize("method", rank_methods) @pytest.mark.parametrize("data", [data_int, data_float]) def test_rank_expr( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(nw_eager_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(nw_eager_constructor) + "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): @@ -83,12 +83,12 @@ def test_rank_expr( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(nw_eager_constructor) and method == "average" + if "pyarrow_table" in str(constructor_eager) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").rank(method=method)) expected_data = {"a": expected[method]} @@ -98,18 +98,18 @@ def test_rank_expr( @pytest.mark.parametrize("method", rank_methods) @pytest.mark.parametrize("data", [data_int, data_float]) def test_rank_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(nw_eager_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor_eager) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(nw_eager_constructor) + "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): @@ -120,12 +120,12 @@ def test_rank_series( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(nw_eager_constructor) and method == "average" + if "pyarrow_table" in str(constructor_eager) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"a": df["a"].rank(method=method)} expected_data = {"a": expected[method]} @@ -146,28 +146,28 @@ def test_rank_series_pandas_namesless() -> None: @pytest.mark.parametrize("method", rank_methods) def test_rank_expr_in_over_context( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "cudf")): + if any(x in str(constructor) for x in ("pyarrow_table", "dask", "cudf")): # Pyarrow raises: # > pyarrow.lib.ArrowKeyError: No function registered with name: hash_rank # We can handle that to provide a better error message. # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") - df = nw.from_native(nw_frame_constructor(data_float)) + df = nw.from_native(constructor(data_float)) result = ( df.with_columns(a=nw.col("a").rank(method=method).over("b")).sort("i").select("a") @@ -176,9 +176,9 @@ def test_rank_expr_in_over_context( assert_equal_data(result, expected_data) -def test_invalid_method_raise(nw_eager_constructor: ConstructorEager) -> None: +def test_invalid_method_raise(constructor_eager: ConstructorEager) -> None: method = "invalid_method_name" - df = nw.from_native(nw_eager_constructor(data_float)) + df = nw.from_native(constructor_eager(data_float)) msg = ( "Ranking method must be one of {'average', 'min', 'max', 'dense', 'ordinal'}. " @@ -196,27 +196,27 @@ def test_invalid_method_raise(nw_eager_constructor: ConstructorEager) -> None: @pytest.mark.parametrize("data", [data_int, data_float]) def test_lazy_rank_expr( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(nw_frame_constructor) + "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) @@ -225,12 +225,12 @@ def test_lazy_rank_expr( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(nw_frame_constructor) and method == "average" + if "pyarrow_table" in str(constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(a=nw.col("a").rank(method=method)).sort("i").select("a") expected_data = {"a": expected[method]} @@ -241,27 +241,27 @@ def test_lazy_rank_expr( @pytest.mark.parametrize("data", [data_int, data_float]) def test_lazy_rank_expr_desc( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], data: dict[str, list[float]], ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() if ( - "pandas_pyarrow" in str(nw_frame_constructor) + "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1) and isinstance(data["a"][0], int) ): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) @@ -270,12 +270,12 @@ def test_lazy_rank_expr_desc( ValueError, match=r"`rank` with `method='average' is not supported for pyarrow backend.", ) - if "pyarrow_table" in str(nw_frame_constructor) and method == "average" + if "pyarrow_table" in str(constructor) and method == "average" else does_not_raise() ) with context: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns(a=nw.col("a").rank(method=method, descending=True)) @@ -289,28 +289,28 @@ def test_lazy_rank_expr_desc( @pytest.mark.parametrize("method", rank_methods) def test_rank_expr_in_over_desc( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, method: Literal["average", "min", "max", "dense", "ordinal"], ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask", "cudf")): + if any(x in str(constructor) for x in ("pyarrow_table", "dask", "cudf")): # Pyarrow raises: # > pyarrow.lib.ArrowKeyError: No function registered with name: hash_rank # We can handle that to provide a better error message. # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") - df = nw.from_native(nw_frame_constructor(data_float)) + df = nw.from_native(constructor(data_float)) result = ( df.with_columns(a=nw.col("a").rank(method=method, descending=True).over("b")) @@ -322,32 +322,32 @@ def test_rank_expr_in_over_desc( def test_rank_with_order_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # `rank` is not implemented in Dask request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip(reason="too old") - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") context = ( pytest.raises(NotImplementedError) - if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")) + if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")) else does_not_raise() ) df = nw.from_native( - nw_frame_constructor( + constructor( {"a": [1, 1, 2, 2, 3, 3], "b": [3, None, 4, 3, 5, 6], "i": list(range(6))} ) ) @@ -365,7 +365,7 @@ def test_rank_with_order_by( with context: # gh 3177 - df = nw.from_native(nw_frame_constructor({"i": [0, 1, 2], "j": [1, 2, 1]})) + df = nw.from_native(constructor({"i": [0, 1, 2], "j": [1, 2, 1]})) result = ( df.with_columns(z=nw.col("j").rank("min").over(order_by="i")) .sort("i") @@ -376,28 +376,28 @@ def test_rank_with_order_by( def test_rank_with_order_by_and_partition_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) + any(x in str(constructor) for x in ("pandas_pyarrow", "modin_pyarrow")) and is_windows() ): # https://github.com/pandas-dev/pandas/issues/61896 pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): # `rank` is not implemented in Dask # pyarrow only supports aggregations in `over(partition_by=...)` # cudf: https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "pandas_pyarrow" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 1): + if "pandas_pyarrow" in str(constructor) and PANDAS_VERSION < (2, 1): pytest.skip(reason="bug in old version") - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip(reason="too old") - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip(reason="too old version") df = nw.from_native( - nw_frame_constructor( + constructor( { "a": [1, 1, 2, 2, 3, 3], "b": [3, None, 4, 3, 5, 6], @@ -408,7 +408,7 @@ def test_rank_with_order_by_and_partition_by( ) context = ( pytest.raises(NotImplementedError) - if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")) + if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")) else does_not_raise() ) with context: diff --git a/tests/expr_and_series/reduction_test.py b/tests/expr_and_series/reduction_test.py index 4350b253cc..cba75767ea 100644 --- a/tests/expr_and_series/reduction_test.py +++ b/tests/expr_and_series/reduction_test.py @@ -26,12 +26,12 @@ ], ) def test_scalar_reduction_select( - nw_frame_constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] + constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(*expr) assert_equal_data(result, expected) @@ -53,17 +53,17 @@ def test_scalar_reduction_select( ], ) def test_scalar_reduction_with_columns( - nw_frame_constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] + constructor: Constructor, expr: list[Any], expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(*expr).select(*expected.keys()) assert_equal_data(result, expected) -def test_empty_scalar_reduction_select(nw_frame_constructor: Constructor) -> None: +def test_empty_scalar_reduction_select(constructor: Constructor) -> None: data = { "str": [*"abcde"], "int": [0, 1, 2, 3, 4], @@ -78,7 +78,7 @@ def test_empty_scalar_reduction_select(nw_frame_constructor: Constructor) -> Non "sum": nw.col("int").sum(), } - df = nw.from_native(nw_frame_constructor(data)).filter(str="z") + df = nw.from_native(constructor(data)).filter(str="z") result = df.select(**expressions) expected = { @@ -92,8 +92,8 @@ def test_empty_scalar_reduction_select(nw_frame_constructor: Constructor) -> Non assert_equal_data(result, expected) -def test_empty_scalar_reduction_with_columns(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_empty_scalar_reduction_with_columns(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { @@ -110,7 +110,7 @@ def test_empty_scalar_reduction_with_columns(nw_frame_constructor: Constructor) "sum": nw.col("int").sum(), } - df = nw.from_native(nw_frame_constructor(data)).filter(str="z") + df = nw.from_native(constructor(data)).filter(str="z") result = df.with_columns(**expressions) expected: dict[str, list[Any]] = { k: [] for k in chain(df.collect_schema(), expressions) @@ -118,13 +118,13 @@ def test_empty_scalar_reduction_with_columns(nw_frame_constructor: Constructor) assert_equal_data(result, expected) -def test_empty_scalar_reduction_series(nw_eager_constructor: ConstructorEager) -> None: +def test_empty_scalar_reduction_series(constructor_eager: ConstructorEager) -> None: data = { "str": [*"abcde"], "int": [0, 1, 2, 3, 4], "bool": [True, False, False, True, False], } - df = nw.from_native(nw_eager_constructor(data), eager_only=True).filter(str="z") + df = nw.from_native(constructor_eager(data), eager_only=True).filter(str="z") result_s = { "all": [df["bool"].all()], "any": [df["bool"].any()], diff --git a/tests/expr_and_series/replace_strict_test.py b/tests/expr_and_series/replace_strict_test.py index b70bc661d6..e0fbcecd06 100644 --- a/tests/expr_and_series/replace_strict_test.py +++ b/tests/expr_and_series/replace_strict_test.py @@ -25,7 +25,8 @@ def xfail_if_no_default(constructor: Constructor, request: pytest.FixtureRequest) -> None: - if constructor.is_lazy and not constructor.is_polars: + lazy_non_polars_constructors = ("dask", "duckdb", "ibis", "pyspark", "sqlframe") + if any(x in str(constructor) for x in lazy_non_polars_constructors): reason = "non-polars lazy backends require default parameter to be provided" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -39,18 +40,18 @@ def xfail_if_no_default(constructor: Constructor, request: pytest.FixtureRequest ], ) def test_replace_strict_expr_basic( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, old: Sequence[Any] | Mapping[Any, Any], new: Sequence[Any] | None, return_dtype: DType | None, ) -> None: - xfail_if_no_default(nw_frame_constructor, request) + xfail_if_no_default(constructor, request) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_frame_constructor({"a": ["one", "two", "three"]})) + df = nw.from_native(constructor({"a": ["one", "two", "three"]})) result = df.select(nw.col("a").replace_strict(old, new, return_dtype=return_dtype)) assert_equal_data(result, {"a": [1, 2, 3]}) if return_dtype is not None: @@ -66,26 +67,26 @@ def test_replace_strict_expr_basic( ], ) def test_replace_strict_series_basic( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, old: Sequence[Any] | Mapping[Any, Any], new: Sequence[Any] | None, return_dtype: DType | None, ) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) result = df["a"].replace_strict(old, new, return_dtype=return_dtype) assert_equal_data({"a": result}, {"a": ["one", "two", "three"]}) result = df["a"].replace_strict(old, new, return_dtype=return_dtype) assert_equal_data({"a": result}, {"a": ["one", "two", "three"]}) -def test_replace_strict_non_full(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and polars_lt_v1: +def test_replace_strict_non_full(constructor: Constructor) -> None: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor({"a": [1, 2, 3]})) expr = nw.col("a").replace_strict([1, 3], [3, 4], return_dtype=nw.Int64) if isinstance(df, nw.LazyFrame): # NOTE: non-lazy polars backends raise ValueError since `default=no_default` @@ -96,21 +97,21 @@ def test_replace_strict_non_full(nw_frame_constructor: Constructor) -> None: df.select(expr) -def test_replace_strict_invalid_expr(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: +def test_replace_strict_invalid_expr(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) msg = "`new` argument is required if `old` argument is not a Mapping type" with pytest.raises(TypeError, match=msg): df.select(nw.col("a").replace_strict(old=[1, 2, 3])) -def test_replace_strict_invalid_series(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: +def test_replace_strict_invalid_series(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) msg = "`new` argument is required if `old` argument is not a Mapping type" with pytest.raises(TypeError, match=msg): @@ -128,20 +129,18 @@ def test_replace_strict_pandas_unnamed_series() -> None: @pytest.mark.parametrize("return_dtype", [nw.String(), None]) def test_replace_strict_expr_with_default( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - return_dtype: DType | None, + constructor: Constructor, request: pytest.FixtureRequest, return_dtype: DType | None ) -> None: spark_connect_reason = ( "`mapping_expr[expr]` raises: pyspark.errors.exceptions.base.PySparkTypeError: " "[UNSUPPORTED_DATA_TYPE] Unsupported DataType `Column`." ) - xfail_if_pyspark_connect(nw_frame_constructor, request, reason=spark_connect_reason) + xfail_if_pyspark_connect(constructor, request, reason=spark_connect_reason) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.col("a").replace_strict( [1, 2], ["one", "two"], default="other", return_dtype=return_dtype @@ -152,12 +151,12 @@ def test_replace_strict_expr_with_default( @pytest.mark.parametrize("return_dtype", [nw.String(), None]) def test_replace_strict_series_with_default( - nw_eager_constructor: ConstructorEager, return_dtype: DType | None + constructor_eager: ConstructorEager, return_dtype: DType | None ) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3, 4]})) + df = nw.from_native(constructor_eager({"a": [1, 2, 3, 4]})) result = df.select( df["a"].replace_strict( [1, 2], ["one", "two"], default="other", return_dtype=return_dtype @@ -167,14 +166,14 @@ def test_replace_strict_series_with_default( def test_replace_strict_with_default_and_nulls( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(nw_frame_constructor, request) + xfail_if_pyspark_connect(constructor, request) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, None, 4]})) + df = nw.from_native(constructor({"a": [1, 2, None, 4]})) result = df.select( nw.col("a").replace_strict([1, 2], [10, 20], default=99, return_dtype=nw.Int64) ) @@ -182,14 +181,14 @@ def test_replace_strict_with_default_and_nulls( def test_replace_strict_with_default_mapping( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(nw_frame_constructor, request) + xfail_if_pyspark_connect(constructor, request) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.col("a").replace_strict( {1: "one", 2: "two", 3: None}, default="other", return_dtype=nw.String() @@ -199,15 +198,15 @@ def test_replace_strict_with_default_mapping( def test_replace_strict_with_expressified_default( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(nw_frame_constructor, request) + xfail_if_pyspark_connect(constructor, request) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2, 3, 4], "b": ["beluga", "narwhal", "orca", "vaquita"]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").replace_strict( {1: "one", 2: "two"}, default=nw.col("b"), return_dtype=nw.String @@ -217,14 +216,12 @@ def test_replace_strict_with_expressified_default( assert_equal_data(result, {"a": ["one", "two", "orca", "vaquita"]}) -def test_replace_strict_with_series_default( - nw_eager_constructor: ConstructorEager, -) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: +def test_replace_strict_with_series_default(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2, 3, 4], "b": ["beluga", "narwhal", "orca", "vaquita"]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) series, default = df["a"], df["b"] result = series.replace_strict( {1: "one", 2: "two"}, default=default, return_dtype=nw.String @@ -234,15 +231,15 @@ def test_replace_strict_with_series_default( def test_mapping_key_not_in_expr( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - xfail_if_pyspark_connect(nw_frame_constructor, request) + xfail_if_pyspark_connect(constructor, request) - if "polars" in str(nw_frame_constructor) and polars_lt_v1: + if "polars" in str(constructor) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").replace_strict({1: "one", 2: "two", 3: "three"}, default="hundred") @@ -250,12 +247,12 @@ def test_mapping_key_not_in_expr( assert_equal_data(result, {"a": ["one", "two"]}) -def test_mapping_key_not_in_series(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and polars_lt_v1: +def test_mapping_key_not_in_series(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and polars_lt_v1: pytest.skip(reason=pl_skip_reason) data = {"a": [1, 2]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df["a"].replace_strict({1: "one", 2: "two", 3: "three"}) assert_equal_data({"a": result}, {"a": ["one", "two"]}) diff --git a/tests/expr_and_series/rolling_mean_test.py b/tests/expr_and_series/rolling_mean_test.py index 60d61bb4e1..b4c0b9e656 100644 --- a/tests/expr_and_series/rolling_mean_test.py +++ b/tests/expr_and_series/rolling_mean_test.py @@ -39,8 +39,8 @@ } -def test_rolling_mean_expr(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_rolling_mean_expr(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select( **{ name: nw.col("a").rolling_mean(**values["kwargs"]) @@ -55,8 +55,8 @@ def test_rolling_mean_expr(nw_eager_constructor: ConstructorEager) -> None: @pytest.mark.filterwarnings( "ignore:`Series.rolling_mean` is being called from the stable API although considered an unstable feature." ) -def test_rolling_mean_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_rolling_mean_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( **{ @@ -110,7 +110,7 @@ def test_rolling_mean_hypothesis(center: bool, values: list[float]) -> None: # ], ) def test_rolling_mean_expr_lazy_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -118,15 +118,15 @@ def test_rolling_mean_expr_lazy_grouped( *, center: bool, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -135,7 +135,7 @@ def test_rolling_mean_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") @@ -162,18 +162,18 @@ def test_rolling_mean_expr_lazy_grouped( ], ) def test_rolling_mean_expr_lazy_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, *, center: bool, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -181,7 +181,7 @@ def test_rolling_mean_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/rolling_std_test.py b/tests/expr_and_series/rolling_std_test.py index e8ebb8edc0..f027b450d9 100644 --- a/tests/expr_and_series/rolling_std_test.py +++ b/tests/expr_and_series/rolling_std_test.py @@ -70,16 +70,16 @@ @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_std_expr( - nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] + constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): pytest.skip() - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").rolling_std(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -90,16 +90,16 @@ def test_rolling_std_expr( ) @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_std_series( - nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] + constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): pytest.skip() name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].rolling_std(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -188,7 +188,7 @@ def test_rolling_std_series( ], ) def test_rolling_std_expr_lazy_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -196,14 +196,14 @@ def test_rolling_std_expr_lazy_ungrouped( center: bool, ddof: int, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() - if "dask" in str(nw_frame_constructor) and ddof != 1: + if "dask" in str(constructor) and ddof != 1: # Only `ddof=1` is supported pytest.skip() data = { @@ -211,7 +211,7 @@ def test_rolling_std_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") @@ -300,7 +300,7 @@ def test_rolling_std_expr_lazy_ungrouped( ], ) def test_rolling_std_expr_lazy_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -310,14 +310,14 @@ def test_rolling_std_expr_lazy_grouped( ddof: int, ) -> None: if ( - ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) - or ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) - or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2)) + ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) + or ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) + or ("pandas" in str(constructor) and PANDAS_VERSION < (1, 2)) ): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -326,7 +326,7 @@ def test_rolling_std_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/rolling_sum_test.py b/tests/expr_and_series/rolling_sum_test.py index 9c920f1dd9..df7b481826 100644 --- a/tests/expr_and_series/rolling_sum_test.py +++ b/tests/expr_and_series/rolling_sum_test.py @@ -41,8 +41,8 @@ } -def test_rolling_sum_expr(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_rolling_sum_expr(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.select( **{ name: nw.col("a").rolling_sum(**values["kwargs"]) @@ -67,18 +67,18 @@ def test_rolling_sum_expr(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_rolling_sum_expr_lazy_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, *, center: bool, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -86,7 +86,7 @@ def test_rolling_sum_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") @@ -113,7 +113,7 @@ def test_rolling_sum_expr_lazy_ungrouped( ], ) def test_rolling_sum_expr_lazy_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -121,15 +121,15 @@ def test_rolling_sum_expr_lazy_grouped( *, center: bool, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2): + if "pandas" in str(constructor) and PANDAS_VERSION < (1, 2): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -138,7 +138,7 @@ def test_rolling_sum_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") @@ -155,8 +155,8 @@ def test_rolling_sum_expr_lazy_grouped( @pytest.mark.filterwarnings( "ignore:`Series.rolling_sum` is being called from the stable API although considered an unstable feature." ) -def test_rolling_sum_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_rolling_sum_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( **{ @@ -206,12 +206,12 @@ def test_rolling_sum_series(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_rolling_sum_expr_invalid_params( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, window_size: int, min_samples: int | None, context: Any, ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) with context: df.select( @@ -260,12 +260,12 @@ def test_rolling_sum_expr_invalid_params( ], ) def test_rolling_sum_series_invalid_params( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, window_size: int, min_samples: int | None, context: Any, ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) with context: df["a"].rolling_sum(window_size=window_size, min_samples=min_samples) diff --git a/tests/expr_and_series/rolling_var_test.py b/tests/expr_and_series/rolling_var_test.py index a27e9a23cc..b38ba5f077 100644 --- a/tests/expr_and_series/rolling_var_test.py +++ b/tests/expr_and_series/rolling_var_test.py @@ -59,20 +59,20 @@ @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_var_expr( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any], ) -> None: name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): # TODO(FBruzzesi): Dask is raising the following error: # NotImplementedError: Partition size is less than overlapping window size. # Try using ``df.repartition`` to increase the partition size. request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.col("a").rolling_var(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -83,16 +83,16 @@ def test_rolling_var_expr( ) @pytest.mark.parametrize("kwargs_and_expected", kwargs_and_expected) def test_rolling_var_series( - nw_eager_constructor: ConstructorEager, kwargs_and_expected: dict[str, Any] + constructor_eager: ConstructorEager, kwargs_and_expected: dict[str, Any] ) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1,): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1,): pytest.skip() name = kwargs_and_expected["name"] kwargs = kwargs_and_expected["kwargs"] expected = kwargs_and_expected["expected"] - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].rolling_var(**kwargs).alias(name)) assert_equal_data(result, {name: expected}) @@ -191,7 +191,7 @@ def test_rolling_var_hypothesis_polars(center: bool, values: list[float]) -> Non ], ) def test_rolling_var_expr_lazy_ungrouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -199,14 +199,14 @@ def test_rolling_var_expr_lazy_ungrouped( center: bool, ddof: int, ) -> None: - if ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) or ( - "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3) + if ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) or ( + "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3) ): pytest.skip() - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() - if "dask" in str(nw_frame_constructor) and ddof != 1: + if "dask" in str(constructor) and ddof != 1: # Only `ddof=1` is supported pytest.skip() data = { @@ -214,7 +214,7 @@ def test_rolling_var_expr_lazy_ungrouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") @@ -255,7 +255,7 @@ def test_rolling_var_expr_lazy_ungrouped( ], ) def test_rolling_var_expr_lazy_grouped( - nw_frame_constructor: Constructor, + constructor: Constructor, expected_a: list[float], window_size: int, min_samples: int, @@ -265,14 +265,14 @@ def test_rolling_var_expr_lazy_grouped( ddof: int, ) -> None: if ( - ("polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10)) - or ("duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3)) - or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 2)) + ("polars" in str(constructor) and POLARS_VERSION < (1, 10)) + or ("duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3)) + or ("pandas" in str(constructor) and PANDAS_VERSION < (1, 2)) ): pytest.skip() - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): # unreliable pytest.skip() data = { @@ -281,7 +281,7 @@ def test_rolling_var_expr_lazy_grouped( "b": [1, None, 2, 3, 4, 5, 6], "i": list(range(7)), } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( nw.col("a") diff --git a/tests/expr_and_series/round_test.py b/tests/expr_and_series/round_test.py index 97cba4ea5c..0709ad28b7 100644 --- a/tests/expr_and_series/round_test.py +++ b/tests/expr_and_series/round_test.py @@ -7,9 +7,9 @@ @pytest.mark.parametrize("decimals", [0, 1, 2]) -def test_round(nw_frame_constructor: Constructor, decimals: int) -> None: +def test_round(constructor: Constructor, decimals: int) -> None: data = {"a": [2.12345, 2.56789, 3.901234]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) expected_data = {k: [round(e, decimals) for e in v] for k, v in data.items()} @@ -18,9 +18,9 @@ def test_round(nw_frame_constructor: Constructor, decimals: int) -> None: @pytest.mark.parametrize("decimals", [0, 1, 2]) -def test_round_series(nw_eager_constructor: ConstructorEager, decimals: int) -> None: +def test_round_series(constructor_eager: ConstructorEager, decimals: int) -> None: data = {"a": [1.12345, 2.56789, 3.901234]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) expected_data = {k: [round(e, decimals) for e in v] for k, v in data.items()} diff --git a/tests/expr_and_series/sample_test.py b/tests/expr_and_series/sample_test.py index 7c8c42fed0..4ec44a8712 100644 --- a/tests/expr_and_series/sample_test.py +++ b/tests/expr_and_series/sample_test.py @@ -4,9 +4,9 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: +def test_sample_fraction(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"a": [1, 2, 3] * 10, "b": [4, 5, 6] * 10}), eager_only=True + constructor_eager({"a": [1, 2, 3] * 10, "b": [4, 5, 6] * 10}), eager_only=True ) result_series = df["a"].sample(fraction=0.1).shape @@ -14,9 +14,9 @@ def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: assert result_series == expected_series -def test_sample_with_seed(nw_eager_constructor: ConstructorEager) -> None: +def test_sample_with_seed(constructor_eager: ConstructorEager) -> None: size, n = 100, 10 - df = nw.from_native(nw_eager_constructor({"a": list(range(size))})) + df = nw.from_native(constructor_eager({"a": list(range(size))})) expected = {"res1": [True], "res2": [False]} series = df["a"] seed1 = series.sample(n=n, seed=123) diff --git a/tests/expr_and_series/shift_test.py b/tests/expr_and_series/shift_test.py index 7c79f7f22f..a06ff4a872 100644 --- a/tests/expr_and_series/shift_test.py +++ b/tests/expr_and_series/shift_test.py @@ -22,25 +22,25 @@ } -def test_shift(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_shift(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) result = df.with_columns(nw.col("a", "b", "c").shift(2)).filter(nw.col("i") > 1) expected = {"i": [2, 3, 4], "a": [0, 1, 2], "b": [1, 2, 3], "c": [5, 4, 3]} assert_equal_data(result, expected) -def test_shift_lazy(nw_frame_constructor: Constructor) -> None: +def test_shift_lazy(constructor: Constructor) -> None: data = { "i": [None, 1, 2, 3, 4], "a": [0, 1, 2, 3, 4], "b": [1, 2, 3, 5, 3], "c": [5, 4, 3, 2, 1], } - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a", "b", "c").shift(2).over(order_by="i")).filter( nw.col("i") > 1, ~nw.col("i").is_null() ) @@ -49,17 +49,17 @@ def test_shift_lazy(nw_frame_constructor: Constructor) -> None: def test_shift_lazy_grouped( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("dask", "pyarrow_table", "cudf")): + if any(x in str(constructor) for x in ("dask", "pyarrow_table", "cudf")): # https://github.com/dask/dask/issues/11806 # https://github.com/rapidsai/cudf/issues/18159 request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a").shift(1).over("b", order_by="i")).sort("i") expected = { "i": [0, 1, 2, 3, 4], @@ -70,8 +70,8 @@ def test_shift_lazy_grouped( assert_equal_data(result, expected) -def test_shift_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_shift_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.with_columns(df["a"].shift(2), df["b"].shift(2), df["c"].shift(2)).filter( nw.col("i") > 1 ) @@ -126,8 +126,8 @@ def test_shift_expr_invalid_params(n: Any, context: Any) -> None: ], ) def test_shift_series_invalid_params( - nw_eager_constructor: ConstructorEager, n: Any, context: Any + constructor_eager: ConstructorEager, n: Any, context: Any ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) with context: df["a"].shift(n) diff --git a/tests/expr_and_series/sin_test.py b/tests/expr_and_series/sin_test.py index dd417df474..b1fed2f501 100644 --- a/tests/expr_and_series/sin_test.py +++ b/tests/expr_and_series/sin_test.py @@ -23,15 +23,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sin_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_sin_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").sin()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sin_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_sin_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.sin() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/skew_test.py b/tests/expr_and_series/skew_test.py index 8f69d4c8ff..9be2056dac 100644 --- a/tests/expr_and_series/skew_test.py +++ b/tests/expr_and_series/skew_test.py @@ -17,11 +17,9 @@ ], ) def test_skew_series( - nw_eager_constructor: ConstructorEager, data: list[float], expected: float | None + constructor_eager: ConstructorEager, data: list[float], expected: float | None ) -> None: - result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ - "a" - ].skew() + result = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].skew() assert_equal_data({"a": [result]}, {"a": [expected]}) @@ -38,24 +36,22 @@ def test_skew_series( ) @pytest.mark.filterwarnings("ignore:.*invalid value:RuntimeWarning:dask") def test_skew_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, data: list[float], expected: float | None, request: pytest.FixtureRequest, ) -> None: - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): # https://github.com/ibis-project/ibis/issues/11176 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "pyspark" in str(nw_frame_constructor) and int(request.node.callspec.id[-1]) == 0: + if "pyspark" in str(constructor) and int(request.node.callspec.id[-1]) == 0: # Can not infer schema from empty dataset. pytest.skip() - result = nw.from_native(nw_frame_constructor({"a": data})).select(nw.col("a").skew()) + result = nw.from_native(constructor({"a": data})).select(nw.col("a").skew()) assert_equal_data(result, {"a": [expected]}) - result = nw.from_native(nw_frame_constructor({"a": data})).with_columns( - nw.col("a").skew() - ) + result = nw.from_native(constructor({"a": data})).with_columns(nw.col("a").skew()) assert_equal_data(result, {"a": [expected] * len(data)}) diff --git a/tests/expr_and_series/sqrt_test.py b/tests/expr_and_series/sqrt_test.py index 4b93087d40..057401d594 100644 --- a/tests/expr_and_series/sqrt_test.py +++ b/tests/expr_and_series/sqrt_test.py @@ -22,15 +22,15 @@ @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sqrt_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_sqrt_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").sqrt()) assert_equal_data(result, {"a": expected}) @pytest.mark.filterwarnings("ignore::RuntimeWarning") -def test_sqrt_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_sqrt_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.sqrt() assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/expr_and_series/std_test.py b/tests/expr_and_series/std_test.py index 26dec7a39a..d2b3cb14ef 100644 --- a/tests/expr_and_series/std_test.py +++ b/tests/expr_and_series/std_test.py @@ -17,10 +17,8 @@ @pytest.mark.parametrize("input_data", [data, data_with_nulls]) -def test_std( - nw_frame_constructor: Constructor, input_data: dict[str, list[float | None]] -) -> None: - df = nw.from_native(nw_frame_constructor(input_data)) +def test_std(constructor: Constructor, input_data: dict[str, list[float | None]]) -> None: + df = nw.from_native(constructor(input_data)) result = df.select( nw.col("a").std(ddof=1).alias("a_ddof_1"), nw.col("a").std(ddof=0).alias("a_ddof_0"), @@ -36,9 +34,9 @@ def test_std( @pytest.mark.parametrize("input_data", [data, data_with_nulls]) def test_std_series( - nw_eager_constructor: ConstructorEager, input_data: dict[str, list[float | None]] + constructor_eager: ConstructorEager, input_data: dict[str, list[float | None]] ) -> None: - df = nw.from_native(nw_eager_constructor(input_data), eager_only=True) + df = nw.from_native(constructor_eager(input_data), eager_only=True) result = { "a_ddof_1": [df["a"].std(ddof=1)], "a_ddof_0": [df["a"].std(ddof=0)], diff --git a/tests/expr_and_series/str/contains_test.py b/tests/expr_and_series/str/contains_test.py index 815e3f2852..7935b6c92f 100644 --- a/tests/expr_and_series/str/contains_test.py +++ b/tests/expr_and_series/str/contains_test.py @@ -81,7 +81,7 @@ contains_str_pattern_data, ) def test_expr_contains_str_pattern( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, pattern: str, *, @@ -89,15 +89,15 @@ def test_expr_contains_str_pattern( expected_with_null: dict[str, list[Any]], expected_without_null: dict[str, list[Any]], ) -> None: - if "cudf" in str(nw_frame_constructor) and "(?i)" in pattern: + if "cudf" in str(constructor) and "(?i)" in pattern: request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("pets").str.contains(pattern, literal=literal).alias("match") ) - if "pandas_constructor" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(constructor) and PANDAS_VERSION >= (3,): expected = expected_without_null else: expected = expected_with_null @@ -109,7 +109,7 @@ def test_expr_contains_str_pattern( contains_str_pattern_data, ) def test_series_contains_str_pattern( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, pattern: str, *, @@ -117,13 +117,13 @@ def test_series_contains_str_pattern( expected_with_null: dict[str, list[Any]], expected_without_null: dict[str, list[Any]], ) -> None: - if "cudf" in str(nw_eager_constructor) and "(?i)" in pattern: + if "cudf" in str(constructor_eager) and "(?i)" in pattern: request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(match=df["pets"].str.contains(pattern, literal=literal)) - if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION >= (3,): expected = expected_without_null else: expected = expected_with_null @@ -132,17 +132,17 @@ def test_series_contains_str_pattern( @pytest.mark.parametrize(("expr_data", "literal", "expected"), contains_expr_pattern_data) def test_expr_contains_expr_pattern( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, expr_data: dict[str, list[str]], *, literal: bool, expected: dict[str, list[Any]], ) -> None: - if any(x in str(nw_frame_constructor) for x in EXPR_PATTERN_UNSUPPORTED): + if any(x in str(constructor) for x in EXPR_PATTERN_UNSUPPORTED): request.applymarker(pytest.mark.xfail(reason="Not supported", raises=TypeError)) - df = nw.from_native(nw_frame_constructor(expr_data)) + df = nw.from_native(constructor(expr_data)) result = df.select( nw.col("text").str.contains(nw.col("pattern"), literal=literal).alias("result") ) @@ -151,29 +151,29 @@ def test_expr_contains_expr_pattern( @pytest.mark.parametrize(("expr_data", "literal", "expected"), contains_expr_pattern_data) def test_series_contains_series_pattern( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, request: pytest.FixtureRequest, expr_data: dict[str, list[str]], *, literal: bool, expected: dict[str, list[Any]], ) -> None: - if any(x in str(nw_eager_constructor) for x in EXPR_PATTERN_UNSUPPORTED): + if any(x in str(constructor_eager) for x in EXPR_PATTERN_UNSUPPORTED): request.applymarker(pytest.mark.xfail(reason="Not supported", raises=TypeError)) - df = nw.from_native(nw_eager_constructor(expr_data), eager_only=True) + df = nw.from_native(constructor_eager(expr_data), eager_only=True) result = df.select(result=df["text"].str.contains(df["pattern"], literal=literal)) assert_equal_data(result, expected) -def test_expr_contains_literal_vs_regex(nw_frame_constructor: Constructor) -> None: +def test_expr_contains_literal_vs_regex(constructor: Constructor) -> None: """Test that literal=True vs literal=False behaves differently for regex patterns.""" - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("pets").str.contains("Parrot|dove", literal=False).alias("regex_match"), nw.col("pets").str.contains("Parrot|dove", literal=True).alias("literal_match"), ) - if "pandas_constructor" in str(nw_frame_constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(constructor) and PANDAS_VERSION >= (3,): expected: dict[str, Any] = { "regex_match": [False, False, False, True, True, False], "literal_match": [False, False, False, False, True, False], @@ -186,14 +186,14 @@ def test_expr_contains_literal_vs_regex(nw_frame_constructor: Constructor) -> No assert_equal_data(result, expected) -def test_series_contains_literal_vs_regex(nw_eager_constructor: ConstructorEager) -> None: +def test_series_contains_literal_vs_regex(constructor_eager: ConstructorEager) -> None: """Test that literal=True vs literal=False behaves differently for regex patterns.""" - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select( regex_match=df["pets"].str.contains("Parrot|dove", literal=False), literal_match=df["pets"].str.contains("Parrot|dove", literal=True), ) - if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION >= (3,): + if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION >= (3,): expected: dict[str, Any] = { "regex_match": [False, False, False, True, True, False], "literal_match": [False, False, False, False, True, False], diff --git a/tests/expr_and_series/str/head_test.py b/tests/expr_and_series/str/head_test.py index 6ec38da8a9..d6d09b978e 100644 --- a/tests/expr_and_series/str/head_test.py +++ b/tests/expr_and_series/str/head_test.py @@ -6,15 +6,15 @@ data = {"a": ["foo", "bars"]} -def test_str_head(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_str_head(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").str.head(3)) expected = {"a": ["foo", "bar"]} assert_equal_data(result, expected) -def test_str_head_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_str_head_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = {"a": ["foo", "bar"]} result = df.select(df["a"].str.head(3)) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/len_chars_test.py b/tests/expr_and_series/str/len_chars_test.py index 0aa7fff982..32a726ab26 100644 --- a/tests/expr_and_series/str/len_chars_test.py +++ b/tests/expr_and_series/str/len_chars_test.py @@ -6,15 +6,15 @@ data = {"a": ["foo", "foobar", "Café", "345", "東京"]} -def test_str_len_chars(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_str_len_chars(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").str.len_chars()) expected = {"a": [3, 6, 4, 3, 2]} assert_equal_data(result, expected) -def test_str_len_chars_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_str_len_chars_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = {"a": [3, 6, 4, 3, 2]} result = df.select(df["a"].str.len_chars()) assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/pad_test.py b/tests/expr_and_series/str/pad_test.py index 176c82bfdb..763fd41043 100644 --- a/tests/expr_and_series/str/pad_test.py +++ b/tests/expr_and_series/str/pad_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, ConstructorEager, assert_equal_data -def test_str_pad_start_series(nw_eager_constructor: ConstructorEager) -> None: +def test_str_pad_start_series(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + constructor_eager({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = { @@ -21,9 +21,9 @@ def test_str_pad_start_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_str_pad_start_expr(nw_frame_constructor: Constructor) -> None: +def test_str_pad_start_expr(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = df.select( @@ -38,9 +38,9 @@ def test_str_pad_start_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_str_pad_end_series(nw_eager_constructor: ConstructorEager) -> None: +def test_str_pad_end_series(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + constructor_eager({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = { @@ -55,9 +55,9 @@ def test_str_pad_end_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_str_pad_end_expr(nw_frame_constructor: Constructor) -> None: +def test_str_pad_end_expr(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) + constructor({"a": ["foo", "longer_foo", "longest_fooooooo", "hi", None]}) ) result = df.select( @@ -72,8 +72,8 @@ def test_str_pad_end_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_start_unicode_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_start_unicode_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": ["Café", "345", "東京", None]})) result = df.select(nw.col("a").str.pad_start(6, "日")) expected = {"a": ["日日Café", "日日日345", "日日日日東京", None]} @@ -81,8 +81,8 @@ def test_pad_start_unicode_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_start_unicode_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_start_unicode_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": ["Café", "345", "東京", None]})) result = {"a": df["a"].str.pad_start(6, "日")} expected = {"a": ["日日Café", "日日日345", "日日日日東京", None]} @@ -90,8 +90,8 @@ def test_pad_start_unicode_series(nw_eager_constructor: ConstructorEager) -> Non assert_equal_data(result, expected) -def test_pad_end_unicode_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_end_unicode_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": ["Café", "345", "東京", None]})) result = df.select(nw.col("a").str.pad_end(6, "日")) expected = {"a": ["Café日日", "345日日日", "東京日日日日", None]} @@ -99,8 +99,8 @@ def test_pad_end_unicode_expr(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_pad_end_unicode_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": ["Café", "345", "東京", None]})) +def test_pad_end_unicode_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": ["Café", "345", "東京", None]})) result = {"a": df["a"].str.pad_end(6, "日")} expected = {"a": ["Café日日", "345日日日", "東京日日日日", None]} diff --git a/tests/expr_and_series/str/replace_test.py b/tests/expr_and_series/str/replace_test.py index c5c9968d0e..e6f49f409b 100644 --- a/tests/expr_and_series/str/replace_test.py +++ b/tests/expr_and_series/str/replace_test.py @@ -99,7 +99,7 @@ ("data", "pattern", "value", "n", "literal", "expected"), replace_data ) def test_str_replace_series_scalar( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -107,7 +107,7 @@ def test_str_replace_series_scalar( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.replace( pattern=pattern, value=value, n=n, literal=literal @@ -119,14 +119,14 @@ def test_str_replace_series_scalar( ("data", "pattern", "value", "literal", "expected"), replace_all_data ) def test_str_replace_all_series_scalar( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.replace_all(pattern=pattern, value=value, literal=literal) assert_equal_data({"a": result_series}, expected) @@ -136,7 +136,7 @@ def test_str_replace_all_series_scalar( ("data", "pattern", "value", "n", "literal", "expected"), replace_data ) def test_str_replace_expr_scalar( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, data: dict[str, list[str]], pattern: str, @@ -145,14 +145,14 @@ def test_str_replace_expr_scalar( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): + if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): request.applymarker( pytest.mark.xfail( - reason=f"{nw_frame_constructor} only supports `replace_all`.", + reason=f"{constructor} only supports `replace_all`.", raises=NotImplementedError, ) ) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_df = df.select( nw.col("a").str.replace(pattern=pattern, value=value, n=n, literal=literal) ) @@ -163,14 +163,14 @@ def test_str_replace_expr_scalar( ("data", "pattern", "value", "literal", "expected"), replace_all_data ) def test_str_replace_all_expr_scalar( - nw_frame_constructor: Constructor, + constructor: Constructor, data: dict[str, list[str]], pattern: str, value: str, literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").str.replace_all(pattern=pattern, value=value, literal=literal) ) @@ -181,7 +181,7 @@ def test_str_replace_all_expr_scalar( ("data", "pattern", "value", "n", "literal", "expected"), replace_data_multivalue ) def test_str_replace_series_multivalue( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -190,13 +190,11 @@ def test_str_replace_series_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) - if any( - x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") - ): + df = nw.from_native(constructor_eager(data), eager_only=True) + if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): request.applymarker( pytest.mark.xfail( - reason=f"{nw_eager_constructor} does not support multivalue replacement", + reason=f"{constructor_eager} does not support multivalue replacement", raises=TypeError, ) ) @@ -211,7 +209,7 @@ def test_str_replace_series_multivalue( ("data", "pattern", "value", "literal", "expected"), replace_all_data_multivalue ) def test_str_replace_all_series_multivalue( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], pattern: str, value: str, @@ -219,17 +217,15 @@ def test_str_replace_all_series_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - if any( - x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") - ): + if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): request.applymarker( pytest.mark.xfail( - reason=f"{nw_eager_constructor} only supports `replace_all`.", + reason=f"{constructor_eager} only supports `replace_all`.", raises=TypeError, ) ) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.replace_all( pattern=pattern, value=df[value], literal=literal ) @@ -240,7 +236,7 @@ def test_str_replace_all_series_multivalue( ("data", "pattern", "value", "n", "literal", "expected"), replace_data_multivalue ) def test_str_replace_expr_multivalue( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, data: dict[str, list[str]], pattern: str, @@ -249,25 +245,24 @@ def test_str_replace_expr_multivalue( literal: bool, # noqa: FBT001 expected: dict[str, list[str]], ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): + if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): request.applymarker( pytest.mark.xfail( - reason=f"{nw_frame_constructor} only supports `replace_all`.", + reason=f"{constructor} only supports `replace_all`.", raises=NotImplementedError, ) ) elif any( - x in str(nw_frame_constructor) - for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ): request.applymarker( pytest.mark.xfail( - reason=f"{nw_frame_constructor} does not support multivalue replacement", + reason=f"{constructor} does not support multivalue replacement", raises=TypeError, ) ) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_df = df.select( nw.col("a").str.replace( pattern=pattern, value=nw.col(value), n=n, literal=literal @@ -280,7 +275,7 @@ def test_str_replace_expr_multivalue( ("data", "pattern", "value", "literal", "expected"), replace_all_data_multivalue ) def test_str_replace_all_expr_multivalue( - nw_frame_constructor: Constructor, + constructor: Constructor, data: dict[str, list[str]], pattern: str, value: str, @@ -288,32 +283,29 @@ def test_str_replace_all_expr_multivalue( expected: dict[str, list[str]], request: pytest.FixtureRequest, ) -> None: - if any( - x in str(nw_frame_constructor) - for x in ("dask", "pyarrow", "pandas", "modin", "cudf") - ): + if any(x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf")): request.applymarker( pytest.mark.xfail( - reason=f"{nw_frame_constructor} does not support multivalue replacement", + reason=f"{constructor} does not support multivalue replacement", raises=TypeError, ) ) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.col("a").str.replace_all(pattern=pattern, value=nw.col(value), literal=literal) ) assert_equal_data(result, expected) -def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> None: +def test_str_replace_errors_series(constructor_eager: ConstructorEager) -> None: context: Any only_str_supported = pytest.raises( TypeError, match=r"only supports str replacement values" ) multivalue_binary_n = pytest.raises(Exception, match=r"'n > 1' not yet supported") - df = nw.from_native(nw_eager_constructor({"a": ["abc", "def", "ab"]})) + df = nw.from_native(constructor_eager({"a": ["abc", "def", "ab"]})) ## .str.replace # all eager backends support scalar replacement @@ -322,9 +314,7 @@ def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> No # pyarrow, pandas, modin and cudf do not support multivalue replacement context = nullcontext() - if any( - x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") - ): + if any(x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf")): context = only_str_supported with context: @@ -332,9 +322,7 @@ def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> No # no backends support multivalue AND n > 1; others error out on multivalue context = ( - multivalue_binary_n - if "polars" in str(nw_eager_constructor) - else only_str_supported + multivalue_binary_n if "polars" in str(constructor_eager) else only_str_supported ) with context: df["a"].str.replace("ab", df["a"], n=2) @@ -346,7 +334,7 @@ def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> No context = ( only_str_supported if any( - x in str(nw_eager_constructor) for x in ("pyarrow", "pandas", "modin", "cudf") + x in str(constructor_eager) for x in ("pyarrow", "pandas", "modin", "cudf") ) else nullcontext() ) @@ -354,19 +342,19 @@ def test_str_replace_errors_series(nw_eager_constructor: ConstructorEager) -> No df["a"].str.replace_all("ab", df["a"]) -def test_str_replace_errors_expr(nw_frame_constructor: Constructor) -> None: +def test_str_replace_errors_expr(constructor: Constructor) -> None: context: Any not_implemented = pytest.raises(NotImplementedError) only_str_supported = pytest.raises( TypeError, match=r"only supports str replacement values" ) - df = nw.from_native(nw_frame_constructor({"a": ["abc", "def", "ab"]})) + df = nw.from_native(constructor({"a": ["abc", "def", "ab"]})) ## .str.replace context = ( not_implemented - if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis", "pyspark")) + if any(x in str(constructor) for x in ("duckdb", "ibis", "pyspark")) else nullcontext() ) with context: @@ -374,11 +362,10 @@ def test_str_replace_errors_expr(nw_frame_constructor: Constructor) -> None: ## .str.replace multivalue; some dont implement replace, others dont support multivalue context = nullcontext() - if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis", "pyspark")): + if any(x in str(constructor) for x in ("duckdb", "ibis", "pyspark")): context = not_implemented elif any( - x in str(nw_frame_constructor) - for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ): context = only_str_supported @@ -392,8 +379,7 @@ def test_str_replace_errors_expr(nw_frame_constructor: Constructor) -> None: context = ( only_str_supported if any( - x in str(nw_frame_constructor) - for x in ("dask", "pyarrow", "pandas", "modin", "cudf") + x in str(constructor) for x in ("dask", "pyarrow", "pandas", "modin", "cudf") ) else nullcontext() ) diff --git a/tests/expr_and_series/str/slice_test.py b/tests/expr_and_series/str/slice_test.py index 7f0ea0719f..87486e6927 100644 --- a/tests/expr_and_series/str/slice_test.py +++ b/tests/expr_and_series/str/slice_test.py @@ -15,9 +15,9 @@ [(1, 2, {"a": ["da", "df"]}), (-2, None, {"a": ["as", "as"]})], ) def test_str_slice( - nw_frame_constructor: Constructor, offset: int, length: int | None, expected: Any + constructor: Constructor, offset: int, length: int | None, expected: Any ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("a").str.slice(offset, length)) assert_equal_data(result_frame, expected) @@ -27,9 +27,9 @@ def test_str_slice( [(1, 2, {"a": ["da", "df"]}), (-2, None, {"a": ["as", "as"]})], ) def test_str_slice_series( - nw_eager_constructor: ConstructorEager, offset: int, length: int | None, expected: Any + constructor_eager: ConstructorEager, offset: int, length: int | None, expected: Any ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.slice(offset, length) assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/split_test.py b/tests/expr_and_series/str/split_test.py index 15c3f21157..f206b84e35 100644 --- a/tests/expr_and_series/str/split_test.py +++ b/tests/expr_and_series/str/split_test.py @@ -18,17 +18,16 @@ (",", {"s": [["foo bar"], ["foo_bar"], ["foo_bar_baz"], ["foo", "bar"]]}), ], ) -def test_str_split(nw_frame_constructor: Constructor, by: str, expected: Any) -> None: - if "cudf" not in str(nw_frame_constructor) and ( - str(nw_frame_constructor).startswith("pandas") - and "pyarrow" not in str(nw_frame_constructor) +def test_str_split(constructor: Constructor, by: str, expected: Any) -> None: + if "cudf" not in str(constructor) and ( + str(constructor).startswith("pandas") and "pyarrow" not in str(constructor) ): - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df.select(nw.col("s").str.split(by=by)) return - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("s").str.split(by=by)) assert_equal_data(result_frame, expected) @@ -41,17 +40,17 @@ def test_str_split(nw_frame_constructor: Constructor, by: str, expected: Any) -> ], ) def test_str_split_series( - nw_eager_constructor: ConstructorEager, by: str, expected: Any + constructor_eager: ConstructorEager, by: str, expected: Any ) -> None: - if "cudf" not in str(nw_eager_constructor) and ( - str(nw_eager_constructor).startswith("pandas") - and "pyarrow" not in str(nw_eager_constructor) + if "cudf" not in str(constructor_eager) and ( + str(constructor_eager).startswith("pandas") + and "pyarrow" not in str(constructor_eager) ): - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df["s"].str.split(by=by) return - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["s"].str.split(by=by) assert_equal_data({"s": result_series}, expected) diff --git a/tests/expr_and_series/str/starts_with_ends_with_test.py b/tests/expr_and_series/str/starts_with_ends_with_test.py index 31beae998a..73f60a355d 100644 --- a/tests/expr_and_series/str/starts_with_ends_with_test.py +++ b/tests/expr_and_series/str/starts_with_ends_with_test.py @@ -9,29 +9,29 @@ data = {"a": ["fdas", "edfas"]} -def test_ends_with(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_ends_with(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").str.ends_with("das")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_ends_with_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_ends_with_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].str.ends_with("das")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_starts_with(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)).lazy() +def test_starts_with(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)).lazy() result = df.select(nw.col("a").str.starts_with("fda")) expected = {"a": [True, False]} assert_equal_data(result, expected) -def test_starts_with_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_starts_with_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.select(df["a"].str.starts_with("fda")) expected = {"a": [True, False]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/str/strip_chars_test.py b/tests/expr_and_series/str/strip_chars_test.py index 6546f2576f..8944bce4de 100644 --- a/tests/expr_and_series/str/strip_chars_test.py +++ b/tests/expr_and_series/str/strip_chars_test.py @@ -15,15 +15,15 @@ [(None, {"a": ["foobar", "bar", "baz"]}), ("foo", {"a": ["bar", "bar\n", " baz"]})], ) def test_str_strip_chars( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, characters: str | None, expected: Any, ) -> None: - if "ibis" in str(nw_frame_constructor) and characters is not None: + if "ibis" in str(constructor) and characters is not None: request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("a").str.strip_chars(characters)) assert_equal_data(result_frame, expected) @@ -33,9 +33,9 @@ def test_str_strip_chars( [(None, {"a": ["foobar", "bar", "baz"]}), ("foo", {"a": ["bar", "bar\n", " baz"]})], ) def test_str_strip_chars_series( - nw_eager_constructor: ConstructorEager, characters: str | None, expected: Any + constructor_eager: ConstructorEager, characters: str | None, expected: Any ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.strip_chars(characters) assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/tail_test.py b/tests/expr_and_series/str/tail_test.py index 5e0e41e3af..8aa9d66c02 100644 --- a/tests/expr_and_series/str/tail_test.py +++ b/tests/expr_and_series/str/tail_test.py @@ -6,16 +6,16 @@ data = {"a": ["foo", "bars"]} -def test_str_tail(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_str_tail(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) expected = {"a": ["foo", "ars"]} result_frame = df.select(nw.col("a").str.tail(3)) assert_equal_data(result_frame, expected) -def test_str_tail_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_str_tail_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = {"a": ["foo", "ars"]} result_series = df["a"].str.tail(3) diff --git a/tests/expr_and_series/str/to_date_test.py b/tests/expr_and_series/str/to_date_test.py index 12ef33824c..d1f7558c9f 100644 --- a/tests/expr_and_series/str/to_date_test.py +++ b/tests/expr_and_series/str/to_date_test.py @@ -16,16 +16,16 @@ def test_to_date_with_fmt_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "cudf" in str(nw_eager_constructor) or ( - "pandas" in str(nw_eager_constructor) - and not uses_pyarrow_backend(constructor=nw_eager_constructor) + if "cudf" in str(constructor_eager) or ( + "pandas" in str(constructor_eager) + and not uses_pyarrow_backend(constructor=constructor_eager) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_date( + result = nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_date( format="%Y-%m-%d" ) assert isinstance(result.dtype, nw.Date) @@ -33,37 +33,34 @@ def test_to_date_with_fmt_series( def test_to_date_infer_fmt_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "cudf" in str(nw_eager_constructor) or ( - "pandas" in str(nw_eager_constructor) - and not uses_pyarrow_backend(constructor=nw_eager_constructor) + if "cudf" in str(constructor_eager) or ( + "pandas" in str(constructor_eager) + and not uses_pyarrow_backend(constructor=constructor_eager) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(nw_eager_constructor(data), eager_only=True)[ - "a" - ].str.to_date() + result = nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_date() assert isinstance(result.dtype, nw.Date) assert_equal_data({"a": result}, expected) def test_to_date_with_fmt_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if "cudf" in str(nw_frame_constructor) or ( - "pandas" in str(nw_frame_constructor) - and not uses_pyarrow_backend(constructor=nw_frame_constructor) + if "cudf" in str(constructor) or ( + "pandas" in str(constructor) and not uses_pyarrow_backend(constructor=constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "not implemented" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( a=nw.col("a").str.to_date(format="%Y-%m-%d") ) result_schema = result.collect_schema() @@ -73,25 +70,22 @@ def test_to_date_with_fmt_expr( def test_to_date_infer_fmt_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if "cudf" in str(nw_frame_constructor) or ( - "pandas" in str(nw_frame_constructor) - and not uses_pyarrow_backend(constructor=nw_frame_constructor) + if "cudf" in str(constructor) or ( + "pandas" in str(constructor) and not uses_pyarrow_backend(constructor=constructor) ): reason = "Date type is not supported" request.applymarker(pytest.mark.xfail(reason=reason)) - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): reason = "Cannot infer format" request.applymarker(pytest.mark.xfail(reason=reason)) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "not implemented" request.applymarker(pytest.mark.xfail(reason=reason)) - result = nw.from_native(nw_frame_constructor(data)).select( - a=nw.col("a").str.to_date() - ) + result = nw.from_native(constructor(data)).select(a=nw.col("a").str.to_date()) result_schema = result.collect_schema() assert isinstance(result_schema["a"], nw.Date) diff --git a/tests/expr_and_series/str/to_datetime_test.py b/tests/expr_and_series/str/to_datetime_test.py index 8b16a2919a..b98755a0cc 100644 --- a/tests/expr_and_series/str/to_datetime_test.py +++ b/tests/expr_and_series/str/to_datetime_test.py @@ -23,14 +23,14 @@ data = {"a": ["2020-01-01T12:34:56"]} -def test_to_datetime(nw_frame_constructor: Constructor) -> None: - if "cudf" in str(nw_frame_constructor): +def test_to_datetime(constructor: Constructor) -> None: + if "cudf" in str(constructor): expected = "2020-01-01T12:34:56.000000000" else: expected = "2020-01-01 12:34:56" result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .lazy() .select(b=nw.col("a").str.to_datetime(format="%Y-%m-%dT%H:%M:%S")) ) @@ -41,14 +41,14 @@ def test_to_datetime(nw_frame_constructor: Constructor) -> None: assert str(result_item) == expected -def test_to_datetime_series(nw_eager_constructor: ConstructorEager) -> None: - if "cudf" in str(nw_eager_constructor): +def test_to_datetime_series(constructor_eager: ConstructorEager) -> None: + if "cudf" in str(constructor_eager): expected = "2020-01-01T12:34:56.000000000" else: expected = "2020-01-01 12:34:56" result = ( - nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_datetime( + nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_datetime( format="%Y-%m-%dT%H:%M:%S" ) ).item(0) @@ -80,27 +80,27 @@ def test_to_datetime_series(nw_eager_constructor: ConstructorEager) -> None: ) def test_to_datetime_infer_fmt( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, data: dict[str, list[str]], expected: str, expected_cudf: str, expected_pyspark: str, ) -> None: if ( - ("polars" in str(nw_frame_constructor) and str(data["a"][0]).isdigit()) - or "duckdb" in str(nw_frame_constructor) - or ("pyspark" in str(nw_frame_constructor) and data["a"][0] == "20240101123456") - or "ibis" in str(nw_frame_constructor) + ("polars" in str(constructor) and str(data["a"][0]).isdigit()) + or "duckdb" in str(constructor) + or ("pyspark" in str(constructor) and data["a"][0] == "20240101123456") + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): expected = expected_cudf - elif "pyspark" in str(nw_frame_constructor): + elif "pyspark" in str(constructor): expected = expected_pyspark result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .lazy() .select(b=nw.col("a").str.to_datetime()) .collect() @@ -131,29 +131,29 @@ def test_to_datetime_infer_fmt( ) def test_to_datetime_series_infer_fmt( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], expected: str, expected_cudf: str, ) -> None: - if "polars" in str(nw_eager_constructor) and str(data["a"][0]).isdigit(): + if "polars" in str(constructor_eager) and str(data["a"][0]).isdigit(): request.applymarker(pytest.mark.xfail) - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): expected = expected_cudf result = ( - nw.from_native(nw_eager_constructor(data), eager_only=True)["a"].str.to_datetime() + nw.from_native(constructor_eager(data), eager_only=True)["a"].str.to_datetime() ).item(0) assert str(result) == expected def test_to_datetime_infer_fmt_from_date( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "ibis")): request.applymarker(pytest.mark.xfail) data = {"z": ["2020-01-01", "2020-01-02", None]} - if "pyspark" in str(nw_frame_constructor): + if "pyspark" in str(constructor): expected = [ datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 2, tzinfo=timezone.utc), @@ -162,9 +162,7 @@ def test_to_datetime_infer_fmt_from_date( else: expected = [datetime(2020, 1, 1), datetime(2020, 1, 2), None] result = ( - nw.from_native(nw_frame_constructor(data)) - .lazy() - .select(nw.col("z").str.to_datetime()) + nw.from_native(constructor(data)).lazy().select(nw.col("z").str.to_datetime()) ) assert_equal_data(result, {"z": expected}) @@ -217,30 +215,25 @@ def test_pyarrow_infer_datetime_raise_inconsistent_date_fmt( @pytest.mark.parametrize("format", [None, "%Y-%m-%dT%H:%M:%S%z"]) def test_to_datetime_tz_aware( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest, format: str | None + constructor: Constructor, request: pytest.FixtureRequest, format: str | None ) -> None: - if is_pyarrow_windows_no_tzdata(nw_frame_constructor) or ( - "sqlframe" in str(nw_frame_constructor) and format is not None and is_windows() + if is_pyarrow_windows_no_tzdata(constructor) or ( + "sqlframe" in str(constructor) and format is not None and is_windows() ): # NOTE: For `sqlframe` see https://github.com/narwhals-dev/narwhals/pull/2263#discussion_r2009101659 pytest.skip() - if "cudf" in str(nw_frame_constructor): + if "cudf" in str(constructor): # cuDF does not yet support timezone-aware datetimes request.applymarker(pytest.mark.xfail) context: AbstractContextManager[Any] = ( pytest.raises(NotImplementedError) - if any(x in str(nw_frame_constructor) for x in ("duckdb", "ibis")) - and format is None + if any(x in str(constructor) for x in ("duckdb", "ibis")) and format is None else does_not_raise() ) - if ( - "polars" in str(nw_frame_constructor) - and POLARS_VERSION >= (1, 33, 0) - and format is None - ): + if "polars" in str(constructor) and POLARS_VERSION >= (1, 33, 0) and format is None: # Polars 1.33.0+ raises an error when parsing timezone-aware datetimes without specifying the timezone context = pytest.raises(ComputeError) - df = nw.from_native(nw_frame_constructor({"a": ["2020-01-01T01:02:03+0100"]})) + df = nw.from_native(constructor({"a": ["2020-01-01T01:02:03+0100"]})) with context: result = df.with_columns(b=nw.col("a").str.to_datetime(format)) assert isinstance(result.collect_schema()["b"], nw.Datetime) diff --git a/tests/expr_and_series/str/to_titlecase_test.py b/tests/expr_and_series/str/to_titlecase_test.py index 472cfb43ad..ae61c3ecd2 100644 --- a/tests/expr_and_series/str/to_titlecase_test.py +++ b/tests/expr_and_series/str/to_titlecase_test.py @@ -19,23 +19,23 @@ def test_str_to_titlecase_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 2): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 2): reason = "version too old, duckdb 1.2 required for LambdaExpression." pytest.skip(reason=reason) - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("a").str.to_titlecase()) assert_equal_data(result_frame, expected) -def test_str_to_titlecase_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_str_to_titlecase_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.to_titlecase() assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py b/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py index 7f29c8f47e..7c5c39a481 100644 --- a/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py +++ b/tests/expr_and_series/str/to_uppercase_to_lowercase_test.py @@ -10,11 +10,9 @@ ("data", "expected"), [({"a": ["foo", "bar"]}, {"a": ["FOO", "BAR"]})] ) def test_str_to_uppercase( - nw_frame_constructor: Constructor, - data: dict[str, list[str]], - expected: dict[str, list[str]], + constructor: Constructor, data: dict[str, list[str]], expected: dict[str, list[str]] ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("a").str.to_uppercase()) assert_equal_data(result_frame, expected) @@ -24,11 +22,11 @@ def test_str_to_uppercase( ("data", "expected"), [({"a": ["foo", "bar"]}, {"a": ["FOO", "BAR"]})] ) def test_str_to_uppercase_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], expected: dict[str, list[str]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.to_uppercase() assert_equal_data({"a": result_series}, expected) @@ -49,11 +47,9 @@ def test_str_to_uppercase_series( ], ) def test_str_to_lowercase( - nw_frame_constructor: Constructor, - data: dict[str, list[str]], - expected: dict[str, list[str]], + constructor: Constructor, data: dict[str, list[str]], expected: dict[str, list[str]] ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result_frame = df.select(nw.col("a").str.to_lowercase()) assert_equal_data(result_frame, expected) @@ -74,11 +70,11 @@ def test_str_to_lowercase( ], ) def test_str_to_lowercase_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, data: dict[str, list[str]], expected: dict[str, list[str]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result_series = df["a"].str.to_lowercase() assert_equal_data({"a": result_series}, expected) diff --git a/tests/expr_and_series/str/zfill_test.py b/tests/expr_and_series/str/zfill_test.py index 70b2f9d8af..78f59cecb1 100644 --- a/tests/expr_and_series/str/zfill_test.py +++ b/tests/expr_and_series/str/zfill_test.py @@ -16,53 +16,51 @@ expected = {"a": ["-01", "+01", "001", "012", "123", "99999", "+9999", None]} -def test_str_zfill( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if uses_pyarrow_backend(nw_frame_constructor) and PANDAS_VERSION < (3,): +def test_str_zfill(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if uses_pyarrow_backend(constructor) and PANDAS_VERSION < (3,): reason = ( "pandas with pyarrow backend doesn't support str.zfill, see " "https://github.com/pandas-dev/pandas/issues/61485" ) request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 5): + if "pandas" in str(constructor) and PANDAS_VERSION < (1, 5): reason = "different zfill behavior" pytest.skip(reason=reason) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 5): reason = ( "`TypeError: argument 'length': 'Expr' object cannot be interpreted as an integer`" "in `expr.str.slice(1, length)`" ) pytest.skip(reason=reason) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").str.zfill(3)) assert_equal_data(result, expected) def test_str_zfill_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if uses_pyarrow_backend(nw_eager_constructor) and PANDAS_VERSION < (3,): + if uses_pyarrow_backend(constructor_eager) and PANDAS_VERSION < (3,): reason = ( "pandas with pyarrow backend doesn't support str.zfill, see " "https://github.com/pandas-dev/pandas/issues/61485" ) request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (1, 5): + if "pandas" in str(constructor_eager) and PANDAS_VERSION < (1, 5): reason = "different zfill behavior" pytest.skip(reason=reason) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (0, 20, 5): + if "polars" in str(constructor_eager) and POLARS_VERSION < (0, 20, 5): reason = ( "`TypeError: argument 'length': 'Expr' object cannot be interpreted as an integer`" "in `expr.str.slice(1, length)`" ) pytest.skip(reason=reason) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df["a"].str.zfill(3) assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/struct_/field_test.py b/tests/expr_and_series/struct_/field_test.py index 2e396f3a48..a351c31500 100644 --- a/tests/expr_and_series/struct_/field_test.py +++ b/tests/expr_and_series/struct_/field_test.py @@ -8,21 +8,19 @@ from tests.utils import PANDAS_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_get_field_expr( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: +def test_get_field_expr(request: pytest.FixtureRequest, constructor: Constructor) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - if any(backend in str(nw_frame_constructor) for backend in ("dask", "modin")): + if any(backend in str(constructor) for backend in ("dask", "modin")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 2, 0): + if "pandas" in str(constructor) and PANDAS_VERSION < (2, 2, 0): pytest.skip() data = {"user": [{"id": "0", "name": "john"}, {"id": "1", "name": "jane"}]} - df_native = nw_frame_constructor(data) + df_native = constructor(data) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): import pandas as pd df_native = cast("pd.DataFrame", df_native).assign( @@ -47,22 +45,22 @@ def test_get_field_expr( def test_get_field_series( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - if any(backend in str(nw_eager_constructor) for backend in ("modin",)): + if any(backend in str(constructor_eager) for backend in ("modin",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2, 0): + if "pandas" in str(constructor_eager) and PANDAS_VERSION < (2, 2, 0): pytest.skip() data = {"user": [{"id": "0", "name": "john"}, {"id": "1", "name": "jane"}]} expected = {"id": ["0", "1"], "name": ["john", "jane"]} _expected = expected.copy() - df_native = nw_eager_constructor(data) + df_native = constructor_eager(data) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): import pandas as pd df_native = cast("pd.DataFrame", df_native).assign( diff --git a/tests/expr_and_series/struct_test.py b/tests/expr_and_series/struct_test.py index e8b3c3afc1..b7f1eae1ca 100644 --- a/tests/expr_and_series/struct_test.py +++ b/tests/expr_and_series/struct_test.py @@ -40,15 +40,15 @@ def maybe_skip(constructor: Constructor | ConstructorEager) -> None: ) def test_struct_positional_exprs( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, exprs: tuple[nw.Expr | list[nw.Expr], ...], ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.struct(*exprs)) expected = { @@ -63,14 +63,14 @@ def test_struct_positional_exprs( def test_struct_named_exprs( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.struct(x="a", y="b").alias("struct")) expected = { @@ -81,14 +81,14 @@ def test_struct_named_exprs( def test_struct_positional_and_named( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.struct("a", z="c").alias("struct")) expected = { @@ -99,14 +99,14 @@ def test_struct_positional_and_named( def test_struct_with_expressions( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select( nw.struct(nw.col("a") * 2, nw.col("c").str.len_chars()).alias("struct") ) @@ -117,14 +117,14 @@ def test_struct_with_expressions( def test_struct_with_literals( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.struct("a", x="c", y=nw.lit(False)).alias("struct")) expected = { @@ -138,8 +138,8 @@ def test_struct_with_literals( assert_equal_data(result, expected) -def test_struct_raise_no_exprs(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_struct_raise_no_exprs(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises(ValueError, match="expected at least 1 expression in 'struct'"): df.select(nw.struct().alias("struct")) @@ -148,16 +148,16 @@ def test_struct_raise_no_exprs(nw_frame_constructor: Constructor) -> None: def test_struct_with_schema( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in UNSUPPORTED_BACKENDS): + if any(x in str(constructor) for x in UNSUPPORTED_BACKENDS): request.applymarker(pytest.mark.xfail) - maybe_skip(constructor=nw_frame_constructor) + maybe_skip(constructor=constructor) data_numeric = {"a": [1, 2, 3], "b": [4.0, 5.0, 6.0]} schema = {"a": nw.Float64(), "b": nw.Float32()} - df = nw.from_native(nw_frame_constructor(data_numeric)) + df = nw.from_native(constructor(data_numeric)) result = df.select(nw.struct("a", "b").cast(nw.Struct(schema)).alias("struct")) assert result.collect_schema()["struct"] == nw.Struct(schema) @@ -167,10 +167,10 @@ def test_struct_with_schema( assert_equal_data(result, expected) -def test_struct_with_series(nw_eager_constructor: ConstructorEager) -> None: - maybe_skip(constructor=nw_eager_constructor) +def test_struct_with_series(constructor_eager: ConstructorEager) -> None: + maybe_skip(constructor=constructor_eager) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) s_a, s_b = df.get_column("a"), df.get_column("b") result = df.select(nw.struct(s_a, s_b).alias("struct")) @@ -181,10 +181,10 @@ def test_struct_with_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_struct_mixed_series_and_exprs(nw_eager_constructor: ConstructorEager) -> None: - maybe_skip(constructor=nw_eager_constructor) +def test_struct_mixed_series_and_exprs(constructor_eager: ConstructorEager) -> None: + maybe_skip(constructor=constructor_eager) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) s_a = df.get_column("a") result = df.select(nw.struct(s_a, nw.col("c")).alias("struct")) @@ -195,10 +195,10 @@ def test_struct_mixed_series_and_exprs(nw_eager_constructor: ConstructorEager) - assert_equal_data(result, expected) -def test_struct_named_with_series(nw_eager_constructor: ConstructorEager) -> None: - maybe_skip(constructor=nw_eager_constructor) +def test_struct_named_with_series(constructor_eager: ConstructorEager) -> None: + maybe_skip(constructor=constructor_eager) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) s_a = df.get_column("a") result = df.select(nw.struct(x=s_a, y="b").alias("struct")) diff --git a/tests/expr_and_series/sum_horizontal_test.py b/tests/expr_and_series/sum_horizontal_test.py index dcd0e1e16f..94cc32d4b0 100644 --- a/tests/expr_and_series/sum_horizontal_test.py +++ b/tests/expr_and_series/sum_horizontal_test.py @@ -8,9 +8,9 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_sumh(nw_frame_constructor: Constructor) -> None: +def test_sumh(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(horizontal_sum=nw.sum_horizontal("a", nw.col("b"))) expected = { "a": [1, 3, 2], @@ -21,18 +21,18 @@ def test_sumh(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_sumh_nullable(nw_frame_constructor: Constructor) -> None: +def test_sumh_nullable(constructor: Constructor) -> None: data = {"a": [1, 8, 3], "b": [4, 5, None], "i": [0, 1, 2]} expected = {"hsum": [5, 13, 3], "i": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(hsum=nw.sum_horizontal("a", "b"), i="i").sort("i") assert_equal_data(result, expected) -def test_sumh_all(nw_frame_constructor: Constructor) -> None: +def test_sumh_all(constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [10, 20, 30]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.sum_horizontal(nw.all().name.suffix("_foo"))) expected = {"a_foo": [11, 22, 33]} assert_equal_data(result, expected) @@ -41,19 +41,19 @@ def test_sumh_all(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_sumh_aggregations(nw_frame_constructor: Constructor) -> None: +def test_sumh_aggregations(constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [10, 20, 30]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.sum_horizontal(nw.all().mean().name.suffix("_foo"))) expected = {"a_foo": [22]} assert_equal_data(result, expected) -def test_sumh_transformations(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_sumh_transformations(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(d=nw.sum_horizontal("a", nw.col("b").sum(), "c")) expected: dict[str, Any] = {"d": [23, 25, 27]} assert_equal_data(result, expected) diff --git a/tests/expr_and_series/sum_test.py b/tests/expr_and_series/sum_test.py index dcf03f8723..6501869a49 100644 --- a/tests/expr_and_series/sum_test.py +++ b/tests/expr_and_series/sum_test.py @@ -9,8 +9,8 @@ @pytest.mark.parametrize("expr", [nw.col("a", "b", "z").sum(), nw.sum("a", "b", "z")]) -def test_expr_sum_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_expr_sum_expr(constructor: Constructor, expr: nw.Expr) -> None: + df = nw.from_native(constructor(data)) result = df.select(expr) expected = {"a": [6], "b": [14], "z": [24.0]} assert_equal_data(result, expected) @@ -18,8 +18,8 @@ def test_expr_sum_expr(nw_frame_constructor: Constructor, expr: nw.Expr) -> None @pytest.mark.parametrize(("col", "expected"), [("a", 6), ("b", 14), ("z", 24.0)]) def test_expr_sum_series( - nw_eager_constructor: ConstructorEager, col: str, expected: float + constructor_eager: ConstructorEager, col: str, expected: float ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] result = series.sum() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/expr_and_series/unary_test.py b/tests/expr_and_series/unary_test.py index 50ee0c2e14..038136a902 100644 --- a/tests/expr_and_series/unary_test.py +++ b/tests/expr_and_series/unary_test.py @@ -8,14 +8,14 @@ from tests.utils import DUCKDB_VERSION, Constructor, ConstructorEager, assert_equal_data -def test_unary(nw_frame_constructor: Constructor, request: pytest.FixtureRequest) -> None: - if "ibis" in str(nw_frame_constructor): +def test_unary(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, None], "z": [7.0, 8.0, 9.0]} - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( a_mean=nw.col("a").mean(), a_median=nw.col("a").median(), a_sum=nw.col("a").sum(), @@ -40,9 +40,9 @@ def test_unary(nw_frame_constructor: Constructor, request: pytest.FixtureRequest assert_equal_data(result, expected) -def test_unary_series(nw_eager_constructor: ConstructorEager) -> None: +def test_unary_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, None], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = { "a_mean": [df["a"].mean()], "a_median": [df["a"].median()], @@ -71,14 +71,14 @@ def test_unary_series(nw_eager_constructor: ConstructorEager) -> None: def test_unary_two_elements( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2], "b": [2, 10], "c": [2.0, None]} - result = nw.from_native(nw_frame_constructor(data)).select( + result = nw.from_native(constructor(data)).select( a_nunique=nw.col("a").n_unique(), a_skew=nw.col("a").skew(), b_nunique=nw.col("b").n_unique(), @@ -97,9 +97,9 @@ def test_unary_two_elements( assert_equal_data(result, expected) -def test_unary_two_elements_series(nw_eager_constructor: ConstructorEager) -> None: +def test_unary_two_elements_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2], "b": [2, 10], "c": [2.0, None]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = { "a_nunique": [df["a"].n_unique()], "a_skew": [df["a"].skew()], @@ -120,26 +120,24 @@ def test_unary_two_elements_series(nw_eager_constructor: ConstructorEager) -> No def test_unary_one_element( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( - nw_frame_constructor - ): + if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): request.applymarker(pytest.mark.xfail) - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1], "b": [2], "c": [None]} # Dask runs into a divide by zero RuntimeWarning for 1 element skew. context = ( pytest.warns(RuntimeWarning, match="invalid value encountered in scalar divide") - if "dask" in str(nw_frame_constructor) + if "dask" in str(constructor) else does_not_raise() ) result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_columns(nw.col("c").cast(nw.Float64)) .select( a_nunique=nw.col("a").n_unique(), @@ -162,9 +160,9 @@ def test_unary_one_element( assert_equal_data(result, expected) -def test_unary_one_element_series(nw_eager_constructor: ConstructorEager) -> None: +def test_unary_one_element_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1], "b": [2], "c": [None]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = { "a_nunique": [df["a"].n_unique()], "a_skew": [df["a"].skew()], diff --git a/tests/expr_and_series/unique_test.py b/tests/expr_and_series/unique_test.py index fa2f482857..c54a0356c7 100644 --- a/tests/expr_and_series/unique_test.py +++ b/tests/expr_and_series/unique_test.py @@ -12,8 +12,8 @@ data_str = {"a": ["x", "x", "y", None]} -def test_unique_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_unique_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) context = ( pytest.raises((InvalidOperationError, NotImplementedError)) if isinstance(df, nw.LazyFrame) @@ -26,11 +26,11 @@ def test_unique_expr(nw_frame_constructor: Constructor) -> None: def test_unique_expr_agg( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark", "ibis")): + if any(x in str(constructor) for x in ("duckdb", "pyspark", "ibis")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("a").unique().sum()) expected = {"a": [3]} assert_equal_data(result, expected) @@ -39,16 +39,16 @@ def test_unique_expr_agg( assert_equal_data(result, expected) -def test_unique_illegal_combination(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_unique_illegal_combination(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.select((nw.col("a").unique() + nw.col("a").unique()).sum()) with pytest.raises((InvalidOperationError, NotImplementedError)): df.select(nw.col("a").unique() + nw.col("a")) -def test_unique_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data_str), eager_only=True)["a"] +def test_unique_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data_str), eager_only=True)["a"] result = series.unique(maintain_order=True) expected = {"a": ["x", "y", None]} assert_equal_data({"a": result}, expected) @@ -57,8 +57,8 @@ def test_unique_series(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data({"a": result}, expected) -def test_unique_series_numeric(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] +def test_unique_series_numeric(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.unique(maintain_order=True) expected = {"a": [1, None, 2]} assert_equal_data({"a": result}, expected) diff --git a/tests/expr_and_series/var_test.py b/tests/expr_and_series/var_test.py index 8bc9cad702..f927dd1ac0 100644 --- a/tests/expr_and_series/var_test.py +++ b/tests/expr_and_series/var_test.py @@ -17,10 +17,8 @@ @pytest.mark.parametrize("input_data", [data, data_with_nulls]) -def test_var( - nw_frame_constructor: Constructor, input_data: dict[str, list[float | None]] -) -> None: - df = nw.from_native(nw_frame_constructor(input_data)) +def test_var(constructor: Constructor, input_data: dict[str, list[float | None]]) -> None: + df = nw.from_native(constructor(input_data)) result = df.select( nw.col("a").var(ddof=1).alias("a_ddof_1"), nw.col("a").var(ddof=0).alias("a_ddof_0"), @@ -40,9 +38,9 @@ def test_var( @pytest.mark.parametrize("input_data", [data, data_with_nulls]) def test_var_series( - nw_eager_constructor: ConstructorEager, input_data: dict[str, list[float | None]] + constructor_eager: ConstructorEager, input_data: dict[str, list[float | None]] ) -> None: - df = nw.from_native(nw_eager_constructor(input_data), eager_only=True) + df = nw.from_native(constructor_eager(input_data), eager_only=True) result = { "a_ddof_1": [df["a"].var(ddof=1)], "a_ddof_0": [df["a"].var(ddof=0)], diff --git a/tests/expr_and_series/when_test.py b/tests/expr_and_series/when_test.py index 48eb103525..aefac8492c 100644 --- a/tests/expr_and_series/when_test.py +++ b/tests/expr_and_series/when_test.py @@ -26,8 +26,8 @@ } -def test_when(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_when(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(value=3).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) @@ -36,15 +36,15 @@ def test_when(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_otherwise(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_when_otherwise(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(3).otherwise(6).alias("a_when")) expected = {"a_when": [3, 6, 6]} assert_equal_data(result, expected) -def test_multiple_conditions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_multiple_conditions(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select( nw.when(nw.col("a") < 3, nw.col("c") < 5.0).then(3).alias("a_when") ) @@ -52,45 +52,45 @@ def test_multiple_conditions(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_no_arg_when_fail(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_no_arg_when_fail(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises((TypeError, ValueError)): df.select(nw.when().then(value=3).alias("a_when")) -def test_value_numpy_array(nw_eager_constructor: ConstructorEager) -> None: +def test_value_numpy_array(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select(nw.when(nw.col("a") == 1).then(np.arange(3, 6)).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) -def test_value_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_value_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) s_data = {"s": [3, 4, 5]} - s = nw.from_native(nw_eager_constructor(s_data))["s"] + s = nw.from_native(constructor_eager(s_data))["s"] assert isinstance(s, nw.Series) result = df.select(nw.when(nw.col("a") == 1).then(s).alias("a_when")) expected = {"a_when": [3, None, None]} assert_equal_data(result, expected) -def test_value_expression(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_value_expression(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a") == 1).then(nw.col("a") + 9).alias("a_when")) expected = {"a_when": [10, None, None]} assert_equal_data(result, expected) -def test_otherwise_numpy_array(nw_eager_constructor: ConstructorEager) -> None: +def test_otherwise_numpy_array(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) arr: _1DArray = np.zeros([3], np.dtype(np.int64)) arr[:3] = 0, 9, 10 @@ -99,18 +99,18 @@ def test_otherwise_numpy_array(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_otherwise_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_otherwise_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) s_data = {"s": [0, 9, 10]} - s = nw.from_native(nw_eager_constructor(s_data))["s"] + s = nw.from_native(constructor_eager(s_data))["s"] assert isinstance(s, nw.Series) result = df.select(nw.when(nw.col("a") == 1).then(-1).otherwise(s).alias("a_when")) expected = {"a_when": [-1, 9, 10]} assert_equal_data(result, expected) -def test_otherwise_expression(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_otherwise_expression(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select( nw.when(nw.col("a") == 1).then(-1).otherwise(nw.col("a") + 7).alias("a_when") ) @@ -118,17 +118,17 @@ def test_otherwise_expression(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_otherwise_into_expr(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_when_then_otherwise_into_expr(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a") > 1).then("c").otherwise("e")) expected = {"c": [7, 5, 6]} assert_equal_data(result, expected) -def test_when_then_broadcasting(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_when_then_broadcasting(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a").sum() > 1).then("c")) expected = {"c": [4.1, 5, 6]} assert_equal_data(result, expected) @@ -137,15 +137,15 @@ def test_when_then_broadcasting(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_then_otherwise_lit_str(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_when_then_otherwise_lit_str(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(nw.when(nw.col("a") > 1).then(nw.col("b")).otherwise(nw.lit("z"))) expected = {"b": ["z", "b", "c"]} assert_equal_data(result, expected) -def test_when_then_otherwise_both_lit(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_when_then_otherwise_both_lit(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select( x1=nw.when(nw.col("a") > 1).then(nw.lit(42)).otherwise(nw.lit(-1)), x2=nw.when(nw.col("a") > 2).then(nw.lit(42)).otherwise(nw.lit(-1)), @@ -154,8 +154,8 @@ def test_when_then_otherwise_both_lit(nw_frame_constructor: Constructor) -> None assert_equal_data(result, expected) -def test_when_then_otherwise_multi_output(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_when_then_otherwise_multi_output(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises(MultiOutputExpressionError): df.select(x1=nw.when(nw.all() > 1).then(nw.col("a", "b"))) with pytest.raises(MultiOutputExpressionError): @@ -182,13 +182,13 @@ def test_when_then_otherwise_aggregate_select( then: nw.Expr | int, otherwise: nw.Expr | int | None, expected: list[int], - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "cudf" in str(nw_frame_constructor) and otherwise is None: + if "cudf" in str(constructor) and otherwise is None: reason = "cudf does not support mixed types" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) result = df.select(a_when=nw.when(condition).then(then).otherwise(otherwise)) assert_equal_data(result, {"a_when": expected}) @@ -213,30 +213,30 @@ def test_when_then_otherwise_aggregate_with_columns( then: nw.Expr | int, otherwise: nw.Expr | int | None, expected: list[int], - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "cudf" in str(nw_frame_constructor) and otherwise is None: + if "cudf" in str(constructor) and otherwise is None: reason = "cudf does not support mixed types" request.applymarker(pytest.mark.xfail(reason=reason)) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) expr = nw.when(condition).then(then).otherwise(otherwise) result = df.with_columns(a_when=expr) assert_equal_data(result.select(nw.col("a_when")), {"a_when": expected}) -def test_when_then_empty(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [-1]})).filter(nw.col("a") > 0) +def test_when_then_empty(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [-1]})).filter(nw.col("a") > 0) result = df.with_columns(nw.when(nw.col("a") == 1).then(nw.lit(1)).alias("new_col")) expected: dict[str, Any] = {"a": [], "new_col": []} assert_equal_data(result, expected) -def test_when_chain_basic_two_conditions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) +def test_when_chain_basic_two_conditions(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -251,8 +251,8 @@ def test_when_chain_basic_two_conditions(nw_frame_constructor: Constructor) -> N assert_equal_data(result, expected) -def test_when_chain_three_conditions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_three_conditions(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.when(nw.col("a") == 1) @@ -269,8 +269,8 @@ def test_when_chain_three_conditions(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_multiple_conditions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) +def test_when_chain_multiple_conditions(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") == 1) @@ -289,8 +289,8 @@ def test_when_chain_multiple_conditions(nw_frame_constructor: Constructor) -> No assert_equal_data(result, expected) -def test_when_chain_no_otherwise(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_no_otherwise(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) result = df.select( nw.when(nw.col("a") == 1).then(10).when(nw.col("a") == 2).then(20).alias("result") @@ -300,8 +300,8 @@ def test_when_chain_no_otherwise(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_first_match_wins(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 5, 10]})) +def test_when_chain_first_match_wins(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 5, 10]})) result = df.select( nw.when(nw.col("a") < 5) @@ -318,8 +318,8 @@ def test_when_chain_first_match_wins(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_all_conditions_false(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) +def test_when_chain_all_conditions_false(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") > 10) @@ -336,8 +336,8 @@ def test_when_chain_all_conditions_false(nw_frame_constructor: Constructor) -> N assert_equal_data(result, expected) -def test_when_chain_mixed_value_types(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_mixed_value_types(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.select( nw.when(nw.col("a") == 1) @@ -354,10 +354,8 @@ def test_when_chain_mixed_value_types(nw_frame_constructor: Constructor) -> None assert_equal_data(result, expected) -def test_when_chain_complex_conditions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native( - nw_frame_constructor({"a": [1, 2, 3, 4, 5], "b": [10, 20, 30, 40, 50]}) - ) +def test_when_chain_complex_conditions(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5], "b": [10, 20, 30, 40, 50]})) result = df.select( nw.when((nw.col("a") == 1) & (nw.col("b") == 10)) @@ -374,8 +372,8 @@ def test_when_chain_complex_conditions(nw_frame_constructor: Constructor) -> Non assert_equal_data(result, expected) -def test_when_chain_with_nulls(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, None, 3, None, 5]})) +def test_when_chain_with_nulls(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, None, 3, None, 5]})) result = df.select( nw.when(nw.col("a") == 1) @@ -393,17 +391,15 @@ def test_when_chain_with_nulls(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_expression_conditions(nw_frame_constructor: Constructor) -> None: - if uses_pyarrow_backend(nw_frame_constructor) or "pyarrow" in str( - nw_frame_constructor - ): +def test_when_chain_expression_conditions(constructor: Constructor) -> None: + if uses_pyarrow_backend(constructor) or "pyarrow" in str(constructor): reason = ( "PyArrow backend doesn't support modulo operator. " "This is a pre-existing PyArrow arithmetic limitation." ) pytest.skip(reason=reason) - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) + df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") % 2 == 0) @@ -424,8 +420,8 @@ def test_when_chain_expression_conditions(nw_frame_constructor: Constructor) -> assert_equal_data(result, expected) -def test_when_chain_value_types_string(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": ["x", "y", "z"]})) +def test_when_chain_value_types_string(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": ["x", "y", "z"]})) result = df.select( nw.when(nw.col("a") == 1) @@ -440,8 +436,8 @@ def test_when_chain_value_types_string(nw_frame_constructor: Constructor) -> Non assert_equal_data(result, expected) -def test_when_chain_value_types_float(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [1.1, 2.2, 3.3]})) +def test_when_chain_value_types_float(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [1.1, 2.2, 3.3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -458,8 +454,8 @@ def test_when_chain_value_types_float(nw_frame_constructor: Constructor) -> None assert_equal_data(result, expected) -def test_when_chain_value_types_mixed(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_value_types_mixed(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.select( nw.when(nw.col("a") == 1) @@ -476,8 +472,8 @@ def test_when_chain_value_types_mixed(nw_frame_constructor: Constructor) -> None assert_equal_data(result, expected) -def test_when_chain_with_columns(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) +def test_when_chain_with_columns(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [10, 20, 30]})) result = df.with_columns( nw.when(nw.col("a") == 1) @@ -492,8 +488,8 @@ def test_when_chain_with_columns(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_when_chain_multiple_columns(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) +def test_when_chain_multiple_columns(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3]})) result = df.select( nw.when(nw.col("a") == 1) @@ -515,9 +511,9 @@ def test_when_chain_multiple_columns(nw_frame_constructor: Constructor) -> None: def test_when_chain_backward_compatible_single_condition( - nw_frame_constructor: Constructor, + constructor: Constructor, ) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor({"a": [1, 2, 3]})) # This is the existing API that must continue to work result = df.select(nw.when(nw.col("a") == 1).then(10).otherwise(20).alias("result")) @@ -526,10 +522,8 @@ def test_when_chain_backward_compatible_single_condition( assert_equal_data(result, expected) -def test_when_chain_two_conditions_no_otherwise( - nw_frame_constructor: Constructor, -) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4, 5]})) +def test_when_chain_two_conditions_no_otherwise(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4, 5]})) result = df.select( nw.when(nw.col("a") == 1).then(10).when(nw.col("a") == 2).then(20).alias("result") @@ -539,13 +533,9 @@ def test_when_chain_two_conditions_no_otherwise( assert_equal_data(result, expected) -def test_when_chain_conditions_on_multiple_columns( - nw_frame_constructor: Constructor, -) -> None: +def test_when_chain_conditions_on_multiple_columns(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor( - {"a": [1, 2, 3, 4], "b": [10, 20, 30, 40], "c": [5, 15, 25, 35]} - ) + constructor({"a": [1, 2, 3, 4], "b": [10, 20, 30, 40], "c": [5, 15, 25, 35]}) ) result = df.select( @@ -565,10 +555,8 @@ def test_when_chain_conditions_on_multiple_columns( assert_equal_data(result, expected) -def test_when_chain_boolean_column_condition(nw_frame_constructor: Constructor) -> None: - df = nw.from_native( - nw_frame_constructor({"a": [True, False, True, False], "b": [1, 2, 3, 4]}) - ) +def test_when_chain_boolean_column_condition(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [True, False, True, False], "b": [1, 2, 3, 4]})) result = df.select( nw.when(nw.col("a")) @@ -587,8 +575,8 @@ def test_when_chain_boolean_column_condition(nw_frame_constructor: Constructor) assert_equal_data(result, expected) -def test_when_chain_branching_does_not_mutate(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) +def test_when_chain_branching_does_not_mutate(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) base_expr = nw.when(nw.col("a") == 1).then(10) derived_expr = base_expr.when(nw.col("a") > 2).then(nw.col("a") * 10).otherwise(0) @@ -598,10 +586,8 @@ def test_when_chain_branching_does_not_mutate(nw_frame_constructor: Constructor) assert_equal_data(result, expected) -def test_when_then_composes_with_expr_operations( - nw_frame_constructor: Constructor, -) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3, 4]})) +def test_when_then_composes_with_expr_operations(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3, 4]})) result = df.select( ( diff --git a/tests/expression_parsing_test.py b/tests/expression_parsing_test.py index 028a652987..138063eb06 100644 --- a/tests/expression_parsing_test.py +++ b/tests/expression_parsing_test.py @@ -52,14 +52,14 @@ ], ) def test_over_pushdown( - nw_frame_constructor: Constructor, expr: nw.Expr, expected: list[float] + constructor: Constructor, expr: nw.Expr, expected: list[float] ) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [-1, 2, 3], "b": [1, 1, 2], "i": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() result = df.select("i", a=expr).sort("i").select("a") assert_equal_data(result, {"a": expected}) @@ -68,18 +68,18 @@ def test_over_pushdown( ("expr", "expected"), [((nw.col("a") - nw.col("a").mean()).over("b"), [-1.5, 1.5, 0])] ) def test_per_group_broadcasting( - nw_frame_constructor: Constructor, + constructor: Constructor, expr: nw.Expr, expected: list[float], request: pytest.FixtureRequest, ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # sigh... request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [-1, 2, 3], "b": [1, 1, 2], "i": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() result = df.select("i", a=expr).sort("i").select("a") assert_equal_data(result, {"a": expected}) @@ -107,13 +107,11 @@ def test_per_group_broadcasting( nw.col("a").filter(nw.col("b").sum().over("c") > 1).sum().over("d"), ], ) -def test_invalid_operations(nw_frame_constructor: Constructor, expr: nw.Expr) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): +def test_invalid_operations(constructor: Constructor, expr: nw.Expr) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() df = nw.from_native( - nw_frame_constructor( - {"a": [-1, 2, 3], "b": [1, 1, 1], "c": [2, 2, 2], "i": [0, 1, 2]} - ) + constructor({"a": [-1, 2, 3], "b": [1, 1, 1], "c": [2, 2, 2], "i": [0, 1, 2]}) ).lazy() with pytest.raises((InvalidOperationError, NotImplementedError)): df.select(a=expr) diff --git a/tests/frame/add_test.py b/tests/frame/add_test.py index 9642aa48b8..166be83fd6 100644 --- a/tests/frame/add_test.py +++ b/tests/frame/add_test.py @@ -6,11 +6,11 @@ from tests.utils import DUCKDB_VERSION, Constructor, assert_equal_data -def test_add(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_add(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns( c=nw.col("a") + nw.col("b"), d=nw.col("a") - nw.col("a").mean(), diff --git a/tests/frame/array_dunder_test.py b/tests/frame/array_dunder_test.py index de17c855a1..d5db653c09 100644 --- a/tests/frame/array_dunder_test.py +++ b/tests/frame/array_dunder_test.py @@ -16,55 +16,55 @@ def test_array_dunder( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) result = df.__array__() np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype="int64")) def test_array_dunder_with_dtype( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) result = df.__array__(object) np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype=object)) def test_array_dunder_with_copy( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < ( + if "polars" in str(constructor_eager) and POLARS_VERSION < ( 0, 20, 28, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) result = df.__array__(copy=True) np.testing.assert_array_equal(result, np.array([[1], [2], [3]], dtype="int64")) - if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < (3,): + if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION < (3,): # If it's pandas, we know that `copy=False` definitely took effect. # So, let's check it! result = df.__array__(copy=False) diff --git a/tests/frame/clone_test.py b/tests/frame/clone_test.py index ca0ecaf4d9..66b9771835 100644 --- a/tests/frame/clone_test.py +++ b/tests/frame/clone_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_clone(nw_eager_constructor: ConstructorEager) -> None: +def test_clone(constructor_eager: ConstructorEager) -> None: expected = {"a": [1, 2], "b": [3, 4]} expected_mod = {"a": [1, 2], "b": [3, 4], "c": [4, 6]} - df = nw.from_native(nw_eager_constructor(expected), eager_only=True) + df = nw.from_native(constructor_eager(expected), eager_only=True) df_clone = df.clone() assert df is not df_clone assert df._compliant_frame is not df_clone._compliant_frame diff --git a/tests/frame/collect_test.py b/tests/frame/collect_test.py index 16085a709e..66ea38e979 100644 --- a/tests/frame/collect_test.py +++ b/tests/frame/collect_test.py @@ -16,25 +16,25 @@ data = {"a": [1, 2], "b": [3, 4]} -def test_collect_to_default_backend(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_collect_to_default_backend(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.lazy().collect().to_native() expected_cls: Any - if "polars" in str(nw_frame_constructor): + if "polars" in str(constructor): pytest.importorskip("polars") import polars as pl expected_cls = pl.DataFrame - elif any(x in str(nw_frame_constructor) for x in ("pandas", "dask")): + elif any(x in str(constructor) for x in ("pandas", "dask")): pytest.importorskip("pandas") import pandas as pd expected_cls = pd.DataFrame - elif "modin" in str(nw_frame_constructor): + elif "modin" in str(constructor): mpd = get_modin() expected_cls = mpd.DataFrame - elif "cudf" in str(nw_frame_constructor): + elif "cudf" in str(constructor): cudf = get_cudf() expected_cls = cudf.DataFrame else: # pyarrow, duckdb, and PySpark @@ -51,13 +51,13 @@ def test_collect_to_default_backend(nw_frame_constructor: Constructor) -> None: ) @pytest.mark.parametrize("backend", ["pandas", Implementation.PANDAS]) def test_collect_to_valid_backend_pandas( - nw_frame_constructor: Constructor, backend: Pandas + constructor: Constructor, backend: Pandas ) -> None: pytest.importorskip("pandas") pytest.importorskip("pyarrow") import pandas as pd - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pd.DataFrame) @@ -67,13 +67,13 @@ def test_collect_to_valid_backend_pandas( ) @pytest.mark.parametrize("backend", ["polars", Implementation.POLARS]) def test_collect_to_valid_backend_polars( - nw_frame_constructor: Constructor, backend: Polars + constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") import polars as pl - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pl.DataFrame) @@ -83,12 +83,12 @@ def test_collect_to_valid_backend_polars( ) @pytest.mark.parametrize("backend", ["pyarrow", Implementation.PYARROW]) def test_collect_to_valid_backend_pyarrow( - nw_frame_constructor: Constructor, backend: Arrow + constructor: Constructor, backend: Arrow ) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=backend).to_native() assert isinstance(result, pa.Table) @@ -96,12 +96,12 @@ def test_collect_to_valid_backend_pyarrow( @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_pandas_mod(nw_frame_constructor: Constructor) -> None: +def test_collect_to_valid_backend_pandas_mod(constructor: Constructor) -> None: pytest.importorskip("pandas") pytest.importorskip("pyarrow") import pandas as pd - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=pd).to_native() assert isinstance(result, pd.DataFrame) @@ -109,12 +109,12 @@ def test_collect_to_valid_backend_pandas_mod(nw_frame_constructor: Constructor) @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_polars_mod(nw_frame_constructor: Constructor) -> None: +def test_collect_to_valid_backend_polars_mod(constructor: Constructor) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") import polars as pl - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=pl).to_native() assert isinstance(result, pl.DataFrame) @@ -122,11 +122,11 @@ def test_collect_to_valid_backend_polars_mod(nw_frame_constructor: Constructor) @pytest.mark.filterwarnings( "ignore:is_sparse is deprecated and will be removed in a future version." ) -def test_collect_to_valid_backend_pyarrow_mod(nw_frame_constructor: Constructor) -> None: +def test_collect_to_valid_backend_pyarrow_mod(constructor: Constructor) -> None: pytest.importorskip("pyarrow") import pyarrow as pa - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.lazy().collect(backend=pa).to_native() assert isinstance(result, pa.Table) @@ -135,15 +135,15 @@ def test_collect_to_valid_backend_pyarrow_mod(nw_frame_constructor: Constructor) "backend", ["foo", Implementation.DASK, Implementation.MODIN, pytest] ) def test_collect_to_invalid_backend( - nw_frame_constructor: Constructor, backend: Literal["foo"] | IntoBackend[Modin | Dask] + constructor: Constructor, backend: Literal["foo"] | IntoBackend[Modin | Dask] ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(ValueError, match="Unsupported `backend` value"): df.lazy().collect(backend=backend).to_native() # type: ignore[arg-type] -def test_collect_with_kwargs(nw_frame_constructor: Constructor) -> None: +def test_collect_with_kwargs(constructor: Constructor) -> None: pl_kwargs = ( {"optimizations": get_polars().QueryOptFlags(predicate_pushdown=False)} if POLARS_VERSION > (1, 29, 0) @@ -155,7 +155,7 @@ def test_collect_with_kwargs(nw_frame_constructor: Constructor) -> None: nw.Implementation.PYARROW: {}, } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.lazy() @@ -167,8 +167,8 @@ def test_collect_with_kwargs(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_collect_empty(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) +def test_collect_empty(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3]})) lf = df.filter(nw.col("a").is_null()).with_columns(b=nw.lit(None)).lazy() result = lf.collect() assert_equal_data(result, {"a": [], "b": []}) diff --git a/tests/frame/columns_test.py b/tests/frame/columns_test.py index fd0eeca2f8..3fda986219 100644 --- a/tests/frame/columns_test.py +++ b/tests/frame/columns_test.py @@ -14,16 +14,16 @@ @pytest.mark.filterwarnings("ignore:Determining|Resolving.*") -def test_columns(nw_frame_constructor: Constructor) -> None: +def test_columns(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.columns expected = ["a", "b", "z"] assert result == expected -def test_iter_columns(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_iter_columns(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected = df.to_dict(as_series=True) result = {series.name: series for series in df.iter_columns()} diff --git a/tests/frame/concat_test.py b/tests/frame/concat_test.py index 08a3d727e6..00beb2ebc1 100644 --- a/tests/frame/concat_test.py +++ b/tests/frame/concat_test.py @@ -15,12 +15,12 @@ from collections.abc import Iterator -def test_concat_horizontal(nw_eager_constructor: ConstructorEager) -> None: +def test_concat_horizontal(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_left = nw.from_native(nw_eager_constructor(data), eager_only=True) + df_left = nw.from_native(constructor_eager(data), eager_only=True) data_right = {"c": [6, 12, -1], "d": [0, -4, 2]} - df_right = nw.from_native(nw_eager_constructor(data_right), eager_only=True) + df_right = nw.from_native(constructor_eager(data_right), eager_only=True) result = nw.concat([df_left, df_right], how="horizontal") expected = { @@ -39,17 +39,14 @@ def test_concat_horizontal(nw_eager_constructor: ConstructorEager) -> None: nw.concat([df_left.lazy()], how="horizontal") -def test_concat_vertical(nw_frame_constructor: Constructor) -> None: +def test_concat_vertical(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} df_left = ( - nw.from_native(nw_frame_constructor(data)) - .lazy() - .rename({"a": "c", "b": "d"}) - .drop("z") + nw.from_native(constructor(data)).lazy().rename({"a": "c", "b": "d"}).drop("z") ) data_right = {"c": [6, 12, -1], "d": [0, -4, 2]} - df_right = nw.from_native(nw_frame_constructor(data_right)).lazy() + df_right = nw.from_native(constructor(data_right)).lazy() result = nw.concat([df_left, df_right], how="vertical") expected = {"c": [1, 3, 2, 6, 12, -1], "d": [4, 4, 6, 0, -4, 2]} @@ -70,7 +67,7 @@ def test_concat_vertical(nw_frame_constructor: Constructor) -> None: nw.concat([df_left, df_left.select("d")], how="vertical").collect() -def test_concat_diagonal(nw_frame_constructor: Constructor) -> None: +def test_concat_diagonal(constructor: Constructor) -> None: data_1 = {"a": [1, 3], "b": [4, 6]} data_2 = {"a": [100, 200], "z": ["x", "y"]} expected = { @@ -79,8 +76,8 @@ def test_concat_diagonal(nw_frame_constructor: Constructor) -> None: "z": [None, None, "x", "y"], } - df_1 = nw.from_native(nw_frame_constructor(data_1)).lazy() - df_2 = nw.from_native(nw_frame_constructor(data_2)).lazy() + df_1 = nw.from_native(constructor(data_1)).lazy() + df_2 = nw.from_native(constructor(data_2)).lazy() result = nw.concat([df_1, df_2], how="diagonal") @@ -91,12 +88,12 @@ def test_concat_diagonal(nw_frame_constructor: Constructor) -> None: def _from_natives( - nw_frame_constructor: Constructor, *sources: dict[str, list[Any]] + constructor: Constructor, *sources: dict[str, list[Any]] ) -> Iterator[nw.LazyFrame[Any]]: - yield from (nw.from_native(nw_frame_constructor(data)).lazy() for data in sources) + yield from (nw.from_native(constructor(data)).lazy() for data in sources) -def test_concat_diagonal_bigger(nw_frame_constructor: Constructor) -> None: +def test_concat_diagonal_bigger(constructor: Constructor) -> None: # NOTE: `ibis.union` doesn't guarantee the order of outputs # https://github.com/narwhals-dev/narwhals/pull/3404#discussion_r2694556781 data_1 = {"idx": [1, 2], "a": [1, 2], "b": [3, 4]} @@ -108,13 +105,13 @@ def test_concat_diagonal_bigger(nw_frame_constructor: Constructor) -> None: "b": [3, 4, None, None, 9, 10], "c": [None, None, 7, 8, 11, 12], } - dfs = _from_natives(nw_frame_constructor, data_1, data_2, data_3) + dfs = _from_natives(constructor, data_1, data_2, data_3) result = nw.concat(dfs, how="diagonal").sort("idx") assert_equal_data(result, expected) def test_concat_diagonal_invalid( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: data_1 = {"a": [1, 3], "b": [4, 6]} data_2 = { @@ -122,8 +119,8 @@ def test_concat_diagonal_invalid( "b": [4, 6], "z": ["x", "y"], } - df_1 = nw.from_native(nw_frame_constructor(data_1)).lazy() - bad_schema = nw.from_native(nw_frame_constructor(data_2)).lazy() + df_1 = nw.from_native(constructor(data_1)).lazy() + bad_schema = nw.from_native(constructor(data_2)).lazy() impl = df_1.implementation request.applymarker( pytest.mark.xfail( diff --git a/tests/frame/double_test.py b/tests/frame/double_test.py index 52901cf196..6a8f5d6333 100644 --- a/tests/frame/double_test.py +++ b/tests/frame/double_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, assert_equal_data -def test_double(nw_frame_constructor: Constructor) -> None: +def test_double(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.all() * 2) expected = {"a": [2, 6, 4], "b": [8, 8, 12], "z": [14.0, 16.0, 18.0]} diff --git a/tests/frame/drop_nulls_test.py b/tests/frame/drop_nulls_test.py index dd289f455d..34d433979d 100644 --- a/tests/frame/drop_nulls_test.py +++ b/tests/frame/drop_nulls_test.py @@ -8,8 +8,8 @@ data = {"alpha": [1.0, 2.0, None, 4.0], "beta gamma": [None, 3.0, None, 5.0]} -def test_drop_nulls(nw_frame_constructor: Constructor) -> None: - result = nw.from_native(nw_frame_constructor(data)).drop_nulls() +def test_drop_nulls(constructor: Constructor) -> None: + result = nw.from_native(constructor(data)).drop_nulls() expected = {"alpha": [2.0, 4.0], "beta gamma": [3.0, 5.0]} assert_equal_data(result, expected) @@ -23,7 +23,7 @@ def test_drop_nulls(nw_frame_constructor: Constructor) -> None: ], ) def test_drop_nulls_subset( - nw_frame_constructor: Constructor, subset: str | list[str], expected: dict[str, float] + constructor: Constructor, subset: str | list[str], expected: dict[str, float] ) -> None: - result = nw.from_native(nw_frame_constructor(data)).drop_nulls(subset=subset) + result = nw.from_native(constructor(data)).drop_nulls(subset=subset) assert_equal_data(result, expected) diff --git a/tests/frame/drop_test.py b/tests/frame/drop_test.py index 4d018a5a8d..233ab3003b 100644 --- a/tests/frame/drop_test.py +++ b/tests/frame/drop_test.py @@ -17,11 +17,9 @@ ("to_drop", "expected"), [("abc", ["b", "z"]), (["abc"], ["b", "z"]), (["abc", "b"], ["z"])], ) -def test_drop( - nw_frame_constructor: Constructor, to_drop: list[str], expected: list[str] -) -> None: +def test_drop(constructor: Constructor, to_drop: list[str], expected: list[str]) -> None: data = {"abc": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) assert df.drop(to_drop).collect_schema().names() == expected if not isinstance(to_drop, str): assert df.drop(*to_drop).collect_schema().names() == expected @@ -29,23 +27,19 @@ def test_drop( @pytest.mark.parametrize("strict", [True, False]) def test_drop_strict( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor, *, strict: bool + request: pytest.FixtureRequest, constructor: Constructor, *, strict: bool ) -> None: - if ( - "polars_lazy" in str(nw_frame_constructor) - and POLARS_VERSION < (1, 0, 0) - and strict - ): + if "polars_lazy" in str(constructor) and POLARS_VERSION < (1, 0, 0) and strict: request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6]} to_drop = ["a", "z"] - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) context: Any if strict: - if "polars_lazy" in str(nw_frame_constructor): + if "polars_lazy" in str(constructor): msg = r"^(\"z\"|z)" else: msg = ( diff --git a/tests/frame/eq_test.py b/tests/frame/eq_test.py index 92223a397d..c100469451 100644 --- a/tests/frame/eq_test.py +++ b/tests/frame/eq_test.py @@ -10,8 +10,8 @@ from tests.utils import Constructor -def test_eq_neq_raise(nw_frame_constructor: Constructor) -> None: +def test_eq_neq_raise(constructor: Constructor) -> None: with pytest.raises(NotImplementedError, match="please use expressions"): - nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) == 0 # noqa: B015 + nw.from_native(constructor({"a": [1, 2, 3]})) == 0 # noqa: B015 with pytest.raises(NotImplementedError, match="please use expressions"): - nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) != 0 # noqa: B015 + nw.from_native(constructor({"a": [1, 2, 3]})) != 0 # noqa: B015 diff --git a/tests/frame/estimated_size_test.py b/tests/frame/estimated_size_test.py index e55f6276ac..78c1cc86f7 100644 --- a/tests/frame/estimated_size_test.py +++ b/tests/frame/estimated_size_test.py @@ -13,8 +13,8 @@ data = {"a": list(range(100))} -def test_estimated_size(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_estimated_size(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) assert df.estimated_size("b") > 0 assert df.estimated_size("kb") == (df.estimated_size("b") / 1024) diff --git a/tests/frame/explode_test.py b/tests/frame/explode_test.py index 3b46c627c9..596eaa82a9 100644 --- a/tests/frame/explode_test.py +++ b/tests/frame/explode_test.py @@ -31,23 +31,20 @@ ) def test_explode_single_col( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, column: str, expected_values: list[int | None], ) -> None: - if any( - backend in str(nw_frame_constructor) - for backend in ("dask", "cudf", "pyarrow_table") - ): + if any(backend in str(constructor) for backend in ("dask", "cudf", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_columns(nw.col(column).cast(nw.List(nw.Int32()))) .explode(column) .select("a", column) @@ -82,24 +79,24 @@ def test_explode_single_col( ) def test_explode_multiple_cols( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, column: str, more_columns: Sequence[str], expected: dict[str, list[str | int | None]], ) -> None: if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("dask", "cudf", "pyarrow_table", "duckdb", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_columns(nw.col(column, *more_columns).cast(nw.List(nw.Int32()))) .explode(column, *more_columns) .select("a", column, *more_columns) @@ -109,15 +106,12 @@ def test_explode_multiple_cols( def test_explode_shape_error( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any( - backend in str(nw_frame_constructor) - for backend in ("dask", "cudf", "pyarrow_table") - ): + if any(backend in str(constructor) for backend in ("dask", "cudf", "pyarrow_table")): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") @@ -127,7 +121,7 @@ def test_explode_shape_error( match=r".*exploded columns (must )?have matching element counts", ): _ = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .lazy() .with_columns(nw.col("l1", "l2", "l3").cast(nw.List(nw.Int32()))) .explode("l1", "l3") @@ -136,15 +130,15 @@ def test_explode_shape_error( def test_explode_invalid_operation_error( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "dask")): + if any(x in str(constructor) for x in ("pyarrow_table", "dask")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 6): + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 6): pytest.skip() with pytest.raises( InvalidOperationError, match="`explode` operation not supported for dtype" ): - _ = nw.from_native(nw_frame_constructor(data)).lazy().explode("a").collect() + _ = nw.from_native(constructor(data)).lazy().explode("a").collect() diff --git a/tests/frame/filter_test.py b/tests/frame/filter_test.py index 80a0505050..f8048d8e4c 100644 --- a/tests/frame/filter_test.py +++ b/tests/frame/filter_test.py @@ -19,17 +19,17 @@ ], ) def test_filter_with_expr_predicates( - nw_frame_constructor: Constructor, + constructor: Constructor, predicates: tuple[nw.Expr, ...], expected: dict[str, list[Any]], ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.filter(*predicates) assert_equal_data(result, expected) -def test_filter_with_series_predicates(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_filter_with_series_predicates(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.filter(df["a"] > 1) expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9.0]} assert_equal_data(result, expected) @@ -47,11 +47,11 @@ def test_filter_with_series_predicates(nw_eager_constructor: ConstructorEager) - ], ) def test_filter_with_boolean_list_predicates_eager( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, predicates: tuple[list[bool], ...], expected: dict[str, list[Any]], ) -> None: - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.filter(*predicates) assert_equal_data(result, expected) @@ -66,27 +66,27 @@ def test_filter_with_boolean_list_predicates_eager( ], ) def test_filter_with_boolean_list_predicates_lazy( - nw_frame_constructor: Constructor, predicates: tuple[list[bool] | nw.Expr, ...] + constructor: Constructor, predicates: tuple[list[bool] | nw.Expr, ...] ) -> None: - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() with pytest.raises(TypeError, match="not supported with Python boolean masks"): df.filter(*predicates) # type: ignore[arg-type] -def test_filter_raise_on_agg_predicate(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_raise_on_agg_predicate(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises(InvalidOperationError): df.filter(nw.col("a").max() > 2).lazy().collect() -def test_filter_raise_on_shape_mismatch(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_raise_on_shape_mismatch(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.filter(nw.col("b").unique() > 2).lazy().collect() -def test_filter_with_constrains_only(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_with_constrains_only(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result_scalar = df.filter(a=3) expected_scalar = {"a": [3], "b": [4], "z": [8.0]} @@ -99,14 +99,14 @@ def test_filter_with_constrains_only(nw_frame_constructor: Constructor) -> None: def test_filter_missing_column( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "pyspark[connect]", "ibis")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) - if "polars" in str(nw_frame_constructor): + df = nw.from_native(constructor(data)) + if "polars" in str(constructor): msg = r"unable to find column \"c\"; valid columns: \[\"a\", \"b\"\, \"z\"\]" elif any(id_ == constructor_id for id_ in ("duckdb", "pyspark")): msg = r"\n\nHint: Did you mean one of these columns: \['a', 'b', 'z'\]?" @@ -116,7 +116,7 @@ def test_filter_missing_column( r"\n\nHint: Did you mean one of these columns: \['a', 'b', 'z'\]?" ) - if "polars_lazy" in str(nw_frame_constructor) and isinstance(df, nw.LazyFrame): + if "polars_lazy" in str(constructor) and isinstance(df, nw.LazyFrame): with pytest.raises(ColumnNotFoundError, match=msg): df.filter(c=5).collect() else: @@ -125,10 +125,10 @@ def test_filter_missing_column( def test_filter_with_predicates_and_constraints( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, ) -> None: # Adapted from https://github.com/narwhals-dev/narwhals/pull/3173/commits/8433b2d75438df98004a3c850ad23628e2376836 - df = nw.from_native(nw_eager_constructor({"a": range(5), "b": [2, 2, 4, 2, 4]})) + df = nw.from_native(constructor_eager({"a": range(5), "b": [2, 2, 4, 2, 4]})) mask = [True, False, True, True, False] mask_2 = [True, True, False, True, False] expected_mask_only = {"a": [0, 2, 3], "b": [2, 4, 2]} @@ -139,7 +139,7 @@ def test_filter_with_predicates_and_constraints( msg = ( r"unable to find column \"c\"; valid columns: \[\"a\", \"b\"\]" - if "polars" in str(nw_eager_constructor) + if "polars" in str(constructor_eager) else ( r"The following columns were not found: \[.*\]" r"\n\nHint: Did you mean one of these columns: \['a', 'b'\]?" @@ -167,12 +167,10 @@ def test_filter_with_predicates_and_constraints( assert_equal_data(result, expected_mixed) -def test_filter_multiple_predicates(nw_frame_constructor: Constructor) -> None: +def test_filter_multiple_predicates(constructor: Constructor) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L175-L202.""" df = nw.from_native( - nw_frame_constructor( - {"a": [1, 1, 1, 2, 2], "b": [1, 1, 2, 2, 2], "c": [1, 1, 2, 3, 4]} - ) + constructor({"a": [1, 1, 1, 2, 2], "b": [1, 1, 2, 2, 2], "c": [1, 1, 2, 3, 4]}) ) # multiple predicates @@ -192,12 +190,10 @@ def test_filter_multiple_predicates(nw_frame_constructor: Constructor) -> None: ) -def test_filter_string_predicate(nw_frame_constructor: Constructor) -> None: +def test_filter_string_predicate(constructor: Constructor) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L204-L210.""" df = nw.from_native( - nw_frame_constructor( - {"description": ["eq", "gt", "ge"], "predicate": ["==", ">", ">="]} - ) + constructor({"description": ["eq", "gt", "ge"], "predicate": ["==", ">", ">="]}) ) expected = {"description": ["eq"], "predicate": ["=="]} result = df.filter(predicate="==") @@ -207,11 +203,9 @@ def test_filter_string_predicate(nw_frame_constructor: Constructor) -> None: @pytest.mark.parametrize( "predicates", [(nw.col("z") < 10,), (nw.col("a") > 0, nw.col("b") > 0)] ) -def test_filter_seq_iterable_all_true( - nw_frame_constructor: Constructor, predicates: Any -) -> None: +def test_filter_seq_iterable_all_true(constructor: Constructor, predicates: Any) -> None: """https://github.com/pola-rs/polars/blob/a4522d719de940be3ef99d494ccd1cd6067475c6/py-polars/tests/unit/lazyframe/test_lazyframe.py#L213-L233.""" - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) predicate = (p for p in predicates) assert_equal_data(df.filter(predicate), data) @@ -219,10 +213,8 @@ def test_filter_seq_iterable_all_true( @pytest.mark.parametrize( "predicates", [(nw.col("z") > 10,), (nw.col("a") < 0, nw.col("b") < 0)] ) -def test_filter_seq_iterable_all_false( - nw_frame_constructor: Constructor, predicates: Any -) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_seq_iterable_all_false(constructor: Constructor, predicates: Any) -> None: + df = nw.from_native(constructor(data)) expected: dict[str, list[Any]] = {"a": [], "b": [], "z": []} predicate = (p for p in predicates) assert_equal_data(df.filter(predicate), expected) diff --git a/tests/frame/from_dict_test.py b/tests/frame/from_dict_test.py index 028eb326ff..4378d9820f 100644 --- a/tests/frame/from_dict_test.py +++ b/tests/frame/from_dict_test.py @@ -28,14 +28,12 @@ def test_from_dict_schema(eager_backend: EagerAllowed) -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) -def test_from_dict_without_backend( - nw_frame_constructor: Constructor, backend: Polars -) -> None: +def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> None: pytest.importorskip("polars") pytest.importorskip("pyarrow") df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) @@ -43,12 +41,8 @@ def test_from_dict_without_backend( assert_equal_data(result, {"c": [1, 2, 3], "d": [4, 5, 6]}) -def test_from_dict_without_backend_invalid(nw_frame_constructor: Constructor) -> None: - df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) - .lazy() - .collect() - ) +def test_from_dict_without_backend_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).lazy().collect() with pytest.raises(TypeError, match="backend"): nw.DataFrame.from_dict({"c": nw.to_native(df["a"]), "d": nw.to_native(df["b"])}) @@ -61,13 +55,13 @@ def test_from_dict_with_backend_invalid() -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) def test_from_dict_one_native_one_narwhals( - nw_frame_constructor: Constructor, backend: Polars + constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) diff --git a/tests/frame/get_column_test.py b/tests/frame/get_column_test.py index ce4e31070d..83c4943342 100644 --- a/tests/frame/get_column_test.py +++ b/tests/frame/get_column_test.py @@ -6,8 +6,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_get_column(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 2], "b": [3, 4]}), eager_only=True) +def test_get_column(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [1, 2], "b": [3, 4]}), eager_only=True) result = df.get_column("a") assert_equal_data({"a": result}, {"a": [1, 2]}) assert result.name == "a" diff --git a/tests/frame/getitem_test.py b/tests/frame/getitem_test.py index deabecab73..c079d154bb 100644 --- a/tests/frame/getitem_test.py +++ b/tests/frame/getitem_test.py @@ -17,26 +17,26 @@ } -def test_slice_column(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native(nw_eager_constructor(data))["a"] +def test_slice_column(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager(data))["a"] assert isinstance(result, nw.Series) assert_equal_data({"a": result}, {"a": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0]}) -def test_slice_rows(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native(nw_eager_constructor(data))[1:] +def test_slice_rows(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager(data))[1:] assert_equal_data(result, {"a": [2.0, 3.0, 4.0, 5.0, 6.0], "b": [12, 13, 14, 15, 16]}) - result = nw.from_native(nw_eager_constructor(data))[2:4] + result = nw.from_native(constructor_eager(data))[2:4] assert_equal_data(result, {"a": [3.0, 4.0], "b": [13, 14]}) def test_slice_rows_with_step( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - result = nw.from_native(nw_eager_constructor(data))[1::2] + result = nw.from_native(constructor_eager(data))[1::2] assert_equal_data(result, {"a": [2.0, 4.0, 6.0], "b": [12, 14, 16]}) @@ -62,23 +62,23 @@ def test_slice_lazy_fails() -> None: _ = nw.from_native(pl.LazyFrame(data))[1:] -def test_slice_int(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native(nw_eager_constructor(data), eager_only=True)[1] +def test_slice_int(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager(data), eager_only=True)[1] assert_equal_data(result, {"a": [2], "b": [12]}) -def test_slice_fails(nw_eager_constructor: ConstructorEager) -> None: +def test_slice_fails(constructor_eager: ConstructorEager) -> None: class Foo: ... with pytest.raises(TypeError, match=r"Unexpected type.*, got:"): - nw.from_native(nw_eager_constructor(data), eager_only=True)[Foo()] # type: ignore[call-overload, unused-ignore] + nw.from_native(constructor_eager(data), eager_only=True)[Foo()] # type: ignore[call-overload, unused-ignore] -def test_gather(nw_eager_constructor: ConstructorEager) -> None: +def test_gather(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df[[0, 3, 1]] expected = {"a": [1.0, 4.0, 2.0], "b": [11, 14, 12]} assert_equal_data(result, expected) @@ -102,11 +102,11 @@ def test_gather_pandas_index() -> None: assert_equal_data(result, expected) -def test_gather_rows_cols(nw_eager_constructor: ConstructorEager) -> None: +def test_gather_rows_cols(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np - native_df = nw_eager_constructor(data) + native_df = constructor_eager(data) df = nw.from_native(native_df, eager_only=True) expected = {"b": [11, 14, 12]} @@ -118,30 +118,30 @@ def test_gather_rows_cols(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_slice_both_list_of_ints(nw_eager_constructor: ConstructorEager) -> None: +def test_slice_both_list_of_ints(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df[[0, 1], [0, 2]] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) def test_slice_both_tuple( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # https://github.com/rapidsai/cudf/issues/18556 request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df[(0, 1), ("a", "c")] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) -def test_slice_int_rows_str_columns(nw_eager_constructor: ConstructorEager) -> None: +def test_slice_int_rows_str_columns(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df[[0, 1], ["a", "c"]] expected = {"a": [1, 2], "c": [7, 8]} assert_equal_data(result, expected) @@ -178,26 +178,26 @@ def test_slice_int_rows_str_columns(nw_eager_constructor: ConstructorEager) -> N ], ) def test_slice_slice_columns( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, row_selector: Any, col_selector: Any, expected: dict[str, list[Any]], ) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df[row_selector] if col_selector is None else df[row_selector, col_selector] assert_equal_data(result, expected) -def test_slice_item(nw_eager_constructor: ConstructorEager) -> None: +def test_slice_item(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2], "b": [4, 5]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) assert df[0, 0] == 1 -def test_slice_edge_cases(nw_eager_constructor: ConstructorEager) -> None: +def test_slice_edge_cases(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) assert df[[], :].shape == (0, 4) assert df[:, []].shape == (0, 0) assert df[[]].shape == (0, 4) @@ -219,11 +219,11 @@ def test_slice_edge_cases(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_get_item_works_with_tuple_and_list_and_range_row_and_col_indexing( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, row_idx: list[int] | tuple[int] | range, col_idx: list[int] | tuple[int] | range, ) -> None: - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) nw_df[row_idx, col_idx] @@ -231,11 +231,11 @@ def test_get_item_works_with_tuple_and_list_and_range_row_and_col_indexing( ("row_idx", "col"), [([0, 2], slice(1)), ((0, 2), slice(1)), (range(2), slice(1))] ) def test_get_item_works_with_tuple_and_list_and_range_row_indexing_and_slice_col_indexing( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, row_idx: list[int] | tuple[int] | range, col: slice, ) -> None: - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) nw_df[row_idx, col] @@ -243,44 +243,42 @@ def test_get_item_works_with_tuple_and_list_and_range_row_indexing_and_slice_col ("row_idx", "col"), [([0, 2], "a"), ((0, 2), "a"), (range(2), "a")] ) def test_get_item_works_with_tuple_and_list_indexing_and_str( - nw_eager_constructor: ConstructorEager, - row_idx: list[int] | tuple[int] | range, - col: str, + constructor_eager: ConstructorEager, row_idx: list[int] | tuple[int] | range, col: str ) -> None: - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) nw_df[row_idx, col] -def test_getitem_ndarray_columns(nw_eager_constructor: ConstructorEager) -> None: +def test_getitem_ndarray_columns(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) arr = np.arange(2) result = nw_df[:, arr] expected = {"col1": ["a", "b", "c", "d"], "col2": [0, 1, 2, 3]} assert_equal_data(result, expected) -def test_getitem_ndarray_columns_labels(nw_eager_constructor: ConstructorEager) -> None: +def test_getitem_ndarray_columns_labels(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) arr: np.ndarray[tuple[int], np.dtype[Any]] = np.array(["col1", "col2"]) # pyright: ignore[reportAssignmentType] result = nw_df[:, arr] expected = {"col1": ["a", "b", "c", "d"], "col2": [0, 1, 2, 3]} assert_equal_data(result, expected) -def test_getitem_negative_slice(nw_eager_constructor: ConstructorEager) -> None: +def test_getitem_negative_slice(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) result = nw_df[-3:-2, ["col3", "col1"]] expected = {"col3": [3], "col1": ["b"]} assert_equal_data(result, expected) @@ -292,20 +290,20 @@ def test_getitem_negative_slice(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data({"col1": result_s}, expected) -def test_zeroth_row_no_columns(nw_eager_constructor: ConstructorEager) -> None: +def test_zeroth_row_no_columns(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np data = {"col1": ["a", "b", "c", "d"], "col2": np.arange(4), "col3": [4, 3, 2, 1]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) columns: list[str] = [] result = nw_df[0, columns] assert result.shape == (0, 0) -def test_single_tuple(nw_eager_constructor: ConstructorEager) -> None: +def test_single_tuple(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) # Technically works but we should probably discourage it # OK if overloads don't match it. result = nw_df[[0, 1],] # type: ignore[index] @@ -313,23 +311,23 @@ def test_single_tuple(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result, expected) -def test_triple_tuple(nw_eager_constructor: ConstructorEager) -> None: +def test_triple_tuple(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3]} with pytest.raises(TypeError, match="Tuples cannot"): - nw.from_native(nw_eager_constructor(data), eager_only=True)[(1, 2, 3)] + nw.from_native(constructor_eager(data), eager_only=True)[(1, 2, 3)] def test_slice_with_series( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: request.applymarker( pytest.mark.xfail( - "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (3,), + "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (3,), reason="https://github.com/pandas-dev/pandas/issues/61311", ) ) data = {"a": [1, 2, 3], "c": [0, 2, 1]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) result = nw_df[nw_df["c"]] expected = {"a": [1, 3, 2], "c": [0, 1, 2]} assert_equal_data(result, expected) @@ -338,32 +336,32 @@ def test_slice_with_series( assert_equal_data(result, expected) -def test_horizontal_slice_with_series(nw_eager_constructor: ConstructorEager) -> None: +def test_horizontal_slice_with_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2], "c": [0, 2], "d": ["c", "a"]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) result = nw_df[nw_df["d"]] expected = {"c": [0, 2], "a": [1, 2]} assert_equal_data(result, expected) def test_horizontal_slice_with_series_2( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: request.applymarker( pytest.mark.xfail( - "pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (3,), + "pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (3,), reason="https://github.com/pandas-dev/pandas/issues/61311", ) ) data = {"a": [1, 2], "c": [0, 2], "d": ["c", "a"]} - nw_df = nw.from_native(nw_eager_constructor(data), eager_only=True) + nw_df = nw.from_native(constructor_eager(data), eager_only=True) result = nw_df[:, nw_df["c"]] expected = {"a": [1, 2], "d": ["c", "a"]} assert_equal_data(result, expected) -def test_native_slice_series(nw_eager_constructor: ConstructorEager) -> None: - s = nw.from_native(nw_eager_constructor({"a": [0, 2, 1]}), eager_only=True)["a"] +def test_native_slice_series(constructor_eager: ConstructorEager) -> None: + s = nw.from_native(constructor_eager({"a": [0, 2, 1]}), eager_only=True)["a"] result = {"a": s[s.to_native()]} expected = {"a": [0, 1, 2]} assert_equal_data(result, expected) @@ -385,18 +383,18 @@ def test_pandas_non_str_columns() -> None: assert result.to_dict(as_series=False) == expected -def test_select_rows_by_name(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [0, 2, 1]}), eager_only=True) +def test_select_rows_by_name(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [0, 2, 1]}), eager_only=True) with pytest.raises(TypeError, match="Unexpected type"): df["a", :] # type: ignore[index] -def test_getitem_boolean_columns(nw_eager_constructor: ConstructorEager) -> None: +def test_getitem_boolean_columns(constructor_eager: ConstructorEager) -> None: pytest.importorskip("numpy") import numpy as np df = nw.from_native( - nw_eager_constructor({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), + constructor_eager({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), eager_only=True, ) result = df[:, [False, True, True]] @@ -408,9 +406,9 @@ def test_getitem_boolean_columns(nw_eager_constructor: ConstructorEager) -> None assert_equal_data(result, expected) -def test_getitem_single_boolean_column(nw_eager_constructor: ConstructorEager) -> None: +def test_getitem_single_boolean_column(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), + constructor_eager({"ab": [1, 2, 3], "bc": [4, 5, 6], "cd": [3, 2, 1]}), eager_only=True, ) with pytest.raises(TypeError): diff --git a/tests/frame/group_by_test.py b/tests/frame/group_by_test.py index 202b4fbce4..788a5363a4 100644 --- a/tests/frame/group_by_test.py +++ b/tests/frame/group_by_test.py @@ -73,8 +73,8 @@ def test_invalid_group_by_dask() -> None: nw.from_native(df_dask).group_by("a").agg(nw.col("b").abs().min()) -def test_group_by_iter(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_group_by_iter(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) expected_keys = [(1,), (3,)] keys = [] for key, sub_df in df.group_by("a"): @@ -108,10 +108,8 @@ def test_group_by_iter_non_str_pandas() -> None: assert_equal_data(groups, expected) -def test_group_by_nw_all(nw_frame_constructor: Constructor) -> None: - df = nw.from_native( - nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 8, 9]}) - ) +def test_group_by_nw_all(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 8, 9]})) result = df.group_by("a").agg(nw.all().sum()).sort("a") expected = {"a": [1, 2], "b": [9, 6], "c": [15, 9]} assert_equal_data(result, expected) @@ -135,21 +133,17 @@ def test_group_by_nw_all(nw_frame_constructor: Constructor) -> None: ], ) def test_group_by_depth_1_agg( - nw_frame_constructor: Constructor, attr: str, expected: dict[str, list[int | float]] + constructor: Constructor, attr: str, expected: dict[str, list[int | float]] ) -> None: - if ( - "pandas_pyarrow" in str(nw_frame_constructor) - and attr == "var" - and PANDAS_VERSION < (2, 1) - ): + if "pandas_pyarrow" in str(constructor) and attr == "var" and PANDAS_VERSION < (2, 1): pytest.skip( "Known issue with variance calculation in pandas 2.0.x with pyarrow backend in groupby operations" ) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 1, 2], "b": [1, None, 2, 3]} expr = getattr(nw.col("b"), attr)() - result = nw.from_native(nw_frame_constructor(data)).group_by("a").agg(expr).sort("a") + result = nw.from_native(constructor(data)).group_by("a").agg(expr).sort("a") assert_equal_data(result, expected) @@ -169,18 +163,16 @@ def test_group_by_depth_1_agg( ) def test_group_by_depth_1_agg_bool_ops( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, values: dict[str, list[bool]], expected: dict[str, list[bool]], ) -> None: - if ("dask-nullable" in request.node.callspec.id) or ( - "cudf" in str(nw_frame_constructor) - ): + if ("dask-nullable" in request.node.callspec.id) or ("cudf" in str(constructor)): request.applymarker(pytest.mark.xfail) data = {"a": [1, 1, 2, 2, 3, 3], **values} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("a") .agg(nw.col("x").all().alias("all"), nw.col("x").any().alias("any")) .sort("a") @@ -191,9 +183,7 @@ def test_group_by_depth_1_agg_bool_ops( @pytest.mark.parametrize( ("attr", "ddof"), [("std", 0), ("var", 0), ("std", 2), ("var", 2)] ) -def test_group_by_depth_1_std_var( - nw_frame_constructor: Constructor, attr: str, ddof: int -) -> None: +def test_group_by_depth_1_std_var(constructor: Constructor, attr: str, ddof: int) -> None: data = {"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]} _pow = 0.5 if attr == "std" else 1 expected = { @@ -204,14 +194,14 @@ def test_group_by_depth_1_std_var( ], } expr = getattr(nw.col("b"), attr)(ddof=ddof) - result = nw.from_native(nw_frame_constructor(data)).group_by("a").agg(expr).sort("a") + result = nw.from_native(constructor(data)).group_by("a").agg(expr).sort("a") assert_equal_data(result, expected) -def test_group_by_median(nw_frame_constructor: Constructor) -> None: +def test_group_by_median(constructor: Constructor) -> None: data = {"a": [1, 1, 1, 2, 2, 2], "b": [5, 4, 6, 7, 3, 2]} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("a") .agg(nw.col("b").median()) .sort("a") @@ -220,12 +210,12 @@ def test_group_by_median(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_group_by_n_unique_w_missing(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_group_by_n_unique_w_missing(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 2], "b": [4, None, 5], "c": [None, None, 7], "d": [1, 1, 3]} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("a") .agg( nw.col("b").n_unique(), @@ -269,9 +259,9 @@ def test_group_by_empty_result_pandas() -> None: ) -def test_group_by_simple_named(nw_frame_constructor: Constructor) -> None: +def test_group_by_simple_named(constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 2, 1]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() result = ( df.group_by("a").agg(b_min=nw.col("b").min(), b_max=nw.col("b").max()).sort("a") ) @@ -279,17 +269,17 @@ def test_group_by_simple_named(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_group_by_simple_unnamed(nw_frame_constructor: Constructor) -> None: +def test_group_by_simple_unnamed(constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 5, 6], "c": [7, 2, 1]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() result = df.group_by("a").agg(nw.col("b").min(), nw.col("c").max()).sort("a") expected = {"a": [1, 2], "b": [4, 6], "c": [7, 1]} assert_equal_data(result, expected) -def test_group_by_multiple_keys(nw_frame_constructor: Constructor) -> None: +def test_group_by_multiple_keys(constructor: Constructor) -> None: data = {"a": [1, 1, 2], "b": [4, 4, 6], "c": [7, 2, 1]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() result = ( df.group_by("a", "b") .agg(c_min=nw.col("c").min(), c_max=nw.col("c").max()) @@ -299,15 +289,13 @@ def test_group_by_multiple_keys(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_key_with_nulls( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "modin" in str(nw_frame_constructor): +def test_key_with_nulls(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "modin" in str(constructor): request.applymarker(pytest.mark.xfail(reason="Modin flaky here", strict=False)) data = {"b": [4, 5, None], "a": [1, 2, 3]} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("b") .agg(nw.len(), nw.col("a").min()) .sort("a") @@ -317,10 +305,10 @@ def test_key_with_nulls( assert_equal_data(result, expected) -def test_key_with_nulls_ignored(nw_frame_constructor: Constructor) -> None: +def test_key_with_nulls_ignored(constructor: Constructor) -> None: data = {"b": [4, 5, None], "a": [1, 2, 3]} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("b", drop_null_keys=True) .agg(nw.len(), nw.col("a").min()) .sort("a") @@ -330,14 +318,14 @@ def test_key_with_nulls_ignored(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_key_with_nulls_iter(nw_eager_constructor: ConstructorEager) -> None: +def test_key_with_nulls_iter(constructor_eager: ConstructorEager) -> None: data = { "b": [None, "4", "5", None, "7"], "a": [None, 1, 2, 3, 4], "c": [None, "4", "3", None, None], } result = dict( - nw.from_native(nw_eager_constructor(data), eager_only=True) + nw.from_native(constructor_eager(data), eager_only=True) .group_by("b", "c", drop_null_keys=True) .__iter__() ) @@ -347,7 +335,7 @@ def test_key_with_nulls_iter(nw_eager_constructor: ConstructorEager) -> None: assert_equal_data(result[("5", "3")], {"b": ["5"], "a": [2], "c": ["3"]}) result = dict( - nw.from_native(nw_eager_constructor(data), eager_only=True) + nw.from_native(constructor_eager(data), eager_only=True) .group_by("b", "c", drop_null_keys=False) .__iter__() ) @@ -356,22 +344,17 @@ def test_key_with_nulls_iter(nw_eager_constructor: ConstructorEager) -> None: assert len(result) == 4 -def test_no_agg(nw_frame_constructor: Constructor) -> None: - result = ( - nw.from_native(nw_frame_constructor(data)) - .group_by(["a", "b"]) - .agg() - .sort("a", "b") - ) +def test_no_agg(constructor: Constructor) -> None: + result = nw.from_native(constructor(data)).group_by(["a", "b"]).agg().sort("a", "b") expected = {"a": [1, 3], "b": [4, 6]} assert_equal_data(result, expected) -def test_group_by_categorical(nw_frame_constructor: Constructor) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyspark", "duckdb", "ibis")): +def test_group_by_categorical(constructor: Constructor) -> None: + if any(x in str(constructor) for x in ("pyspark", "duckdb", "ibis")): pytest.skip(reason="no categorical support") - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < ( 15, ): # pragma: no cover # https://github.com/narwhals-dev/narwhals/issues/1078 @@ -380,7 +363,7 @@ def test_group_by_categorical(nw_frame_constructor: Constructor) -> None: ) data = {"g1": ["a", "a", "b", "b"], "g2": ["x", "y", "x", "z"], "x": [1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.with_columns( g1=nw.col("g1").cast(nw.Categorical()), g2=nw.col("g2").cast(nw.Categorical()) @@ -392,42 +375,40 @@ def test_group_by_categorical(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, data) -def test_group_by_shift_raises(nw_frame_constructor: Constructor) -> None: +def test_group_by_shift_raises(constructor: Constructor) -> None: df_native = {"a": [1, 2, 3], "b": [1, 1, 2]} - df = nw.from_native(nw_frame_constructor(df_native)) + df = nw.from_native(constructor(df_native)) with pytest.raises(InvalidOperationError, match="does not aggregate"): df.group_by("b").agg(nw.col("a").abs()) def test_double_same_aggregation( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("dask",)): + if any(x in str(constructor) for x in ("dask",)): # bugged in dask https://github.com/dask/dask/issues/11612 # and cudf https://github.com/rapidsai/cudf/issues/17649 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.group_by("a").agg(c=nw.col("b").mean(), d=nw.col("b").mean()).sort("a") expected = {"a": [1, 2], "c": [4.5, 6], "d": [4.5, 6]} assert_equal_data(result, expected) def test_all_kind_of_aggs( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("dask",)): + if any(x in str(constructor) for x in ("dask",)): # bugged in dask https://github.com/dask/dask/issues/11612 # and cudf https://github.com/rapidsai/cudf/issues/17649 request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (1, 4): + if "pandas" in str(constructor) and PANDAS_VERSION < (1, 4): pytest.skip( "Pandas < 1.4.0 does not support multiple aggregations with the same column" ) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df = nw.from_native( - nw_frame_constructor({"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]}) - ) + df = nw.from_native(constructor({"a": [1, 1, 1, 2, 2, 2], "b": [4, 5, 6, 0, 5, 5]})) result = ( df.group_by("a") .agg( @@ -473,8 +454,8 @@ def test_pandas_group_by_index_and_column_overlap() -> None: pd.testing.assert_frame_equal(result.to_native(), expected_native) -def test_fancy_functions(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) +def test_fancy_functions(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.group_by("a").agg(nw.all().std(ddof=0)).sort("a") expected = {"a": [1, 2], "b": [0.5, 0.0]} assert_equal_data(result, expected) @@ -537,14 +518,14 @@ def test_fancy_functions(nw_frame_constructor: Constructor) -> None: ], ) def test_group_by_expr( - nw_frame_constructor: Constructor, + constructor: Constructor, keys: list[nw.Expr], aggs: list[nw.Expr], expected: dict[str, list[Any]], sort_by: list[str], ) -> None: data = {"a": [1, 1, 2, 2, -1], "x": [0, 1, 2, 3, 4], "y": [0.5, -0.5, 1.0, -1.0, 1.5]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.group_by(*keys).agg(*aggs).sort(*sort_by) assert_equal_data(result, expected) @@ -560,19 +541,19 @@ def test_group_by_expr( ], ) def test_group_by_raise_if_not_preserves_length( - nw_frame_constructor: Constructor, keys: list[nw.Expr] + constructor: Constructor, keys: list[nw.Expr] ) -> None: data = {"a": [1, 2, 2, None], "b": [0, 1, 2, 3], "x": [1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises((InvalidOperationError, NotImplementedError)): df.group_by(keys).agg(nw.col("x").max()) -def test_group_by_window(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_group_by_window(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 2, 2, None], "b": [1, 1, 2, 2], "x": [1, 2, 3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = ( df.group_by(nw.col("a").mean().over("b")) .agg(nw.col("x").max()) @@ -586,17 +567,17 @@ def test_group_by_window(nw_frame_constructor: Constructor) -> None: "keys", [[nw.col("a").abs()], ["a", nw.col("a").abs().alias("a_test")]] ) def test_group_by_raise_drop_null_keys_with_exprs( - nw_frame_constructor: Constructor, keys: list[nw.Expr | str] + constructor: Constructor, keys: list[nw.Expr | str] ) -> None: data = {"a": [1, 1, 2, 2, -1], "x": [0, 1, 2, 3, 4], "y": [0.5, -0.5, 1.0, -1.0, 1.5]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises( NotImplementedError, match="drop_null_keys cannot be True when keys contains Expr" ): df.group_by(*keys, drop_null_keys=True) # type: ignore[call-overload] -def test_group_by_selector(nw_frame_constructor: Constructor) -> None: +def test_group_by_selector(constructor: Constructor) -> None: data = { "a": [1, 1, 1], "b": [4, 4, 6], @@ -604,7 +585,7 @@ def test_group_by_selector(nw_frame_constructor: Constructor) -> None: "x": [7.5, 8.5, 9.0], } result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by(nw.selectors.by_dtype(nw.Int64), "c") .agg(nw.col("x").mean()) .sort("a", "b") @@ -613,33 +594,29 @@ def test_group_by_selector(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_renaming_edge_case(nw_frame_constructor: Constructor) -> None: +def test_renaming_edge_case(constructor: Constructor) -> None: data = {"a": [0, 0, 0], "_a_tmp": [1, 2, 3], "b": [4, 5, 6]} - result = ( - nw.from_native(nw_frame_constructor(data)) - .group_by(nw.col("a")) - .agg(nw.all().min()) - ) + result = nw.from_native(constructor(data)).group_by(nw.col("a")).agg(nw.all().min()) expected = {"a": [0], "_a_tmp": [1], "b": [4]} assert_equal_data(result, expected) def test_group_by_len_1_column( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: """Based on a failure from marimo. - https://github.com/marimo-team/marimo/blob/036fd3ff89ef3a0e598bebb166637028024f98bc/tests/_plugins/ui/_impl/tables/test_narwhals.py#L1098-L1108 - https://github.com/marimo-team/marimo/blob/036fd3ff89ef3a0e598bebb166637028024f98bc/marimo/_plugins/ui/_impl/tables/narwhals_table.py#L163-L188 """ - if any(x in str(nw_frame_constructor) for x in ("dask",)): + if any(x in str(constructor) for x in ("dask",)): # `dask` # ValueError: conflicting aggregation functions: [('size', 'a'), ('size', 'a')] request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 1, 2, 3, 4]} expected = {"a": [1, 2, 3, 4], "len": [2, 2, 1, 1], "len_a": [2, 2, 1, 1]} result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .group_by("a") .agg(nw.len(), nw.len().alias("len_a")) .sort("a") @@ -674,7 +651,7 @@ def test_group_by_len_1_column( ) def test_group_by_no_preserve_dtype( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, low: NonNestedLiteral, high: NonNestedLiteral, ) -> None: @@ -686,7 +663,7 @@ def test_group_by_no_preserve_dtype( [aggregation that requires a function]: https://github.com/pandas-dev/pandas/issues/57317 """ if ( - "polars" in str(nw_eager_constructor) + "polars" in str(constructor_eager) and isinstance(low, Decimal) and POLARS_VERSION < (1, 21, 0) ): @@ -699,7 +676,7 @@ def test_group_by_no_preserve_dtype( "col_b": [low, low, high, high, None, None, None], } expected = {"col_a": [None, "A", "B"], "n_unique": [2, 3, 2]} - frame = nw.from_native(nw_eager_constructor(data)) + frame = nw.from_native(constructor_eager(data)) result = ( frame.group_by("col_a").agg(n_unique=nw.col("col_b").n_unique()).sort("col_a") ) @@ -708,12 +685,10 @@ def test_group_by_no_preserve_dtype( assert_equal_data(result, expected) -def test_top_level_len(nw_frame_constructor: Constructor) -> None: +def test_top_level_len(constructor: Constructor) -> None: # https://github.com/holoviz/holoviews/pull/6567#issuecomment-3178743331 df = nw.from_native( - nw_frame_constructor( - {"gender": ["m", "f", "f"], "weight": [4, 5, 6], "age": [None, 8, 9]} - ) + constructor({"gender": ["m", "f", "f"], "weight": [4, 5, 6], "age": [None, 8, 9]}) ) result = df.group_by(["gender"]).agg(nw.all().len()).sort("gender") expected = {"gender": ["f", "m"], "weight": [2, 1], "age": [2, 1]} @@ -742,7 +717,7 @@ def test_top_level_len(nw_frame_constructor: Constructor) -> None: ids=["no-sort", "sort-descending", "NA-order-nulls-first", "NA-order-nulls-last"], ) def test_group_by_agg_first( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, keys: Sequence[str], aggs: Sequence[str], expected: Mapping[str, Any], @@ -751,7 +726,7 @@ def test_group_by_agg_first( ) -> None: request.applymarker( pytest.mark.xfail( - "pyarrow_table" in str(nw_eager_constructor) and (PYARROW_VERSION < (14, 0)), + "pyarrow_table" in str(constructor_eager) and (PYARROW_VERSION < (14, 0)), reason="https://github.com/apache/arrow/issues/36709", raises=NotImplementedError, ) @@ -761,7 +736,7 @@ def test_group_by_agg_first( "b": [1, 2, 3, 4, 5, 6], "c": [None, "A", "A", None, "B", "B"], } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) if pre_sort: df = df.sort(aggs, **pre_sort) result = df.group_by(keys).agg(nw.col(aggs).first()).sort(keys) @@ -784,7 +759,7 @@ def test_group_by_agg_first( ids=["no-sort", "sort-descending", "NA-order-nulls-first", "NA-order-nulls-last"], ) def test_group_by_agg_last( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, keys: Sequence[str], aggs: Sequence[str], expected: Mapping[str, Any], @@ -793,7 +768,7 @@ def test_group_by_agg_last( ) -> None: request.applymarker( pytest.mark.xfail( - "pyarrow_table" in str(nw_eager_constructor) and (PYARROW_VERSION < (14, 0)), + "pyarrow_table" in str(constructor_eager) and (PYARROW_VERSION < (14, 0)), reason="https://github.com/apache/arrow/issues/36709", raises=NotImplementedError, ) @@ -803,19 +778,19 @@ def test_group_by_agg_last( "b": [1, 2, 3, 4, 5, 6], "c": [None, "A", "A", None, "B", "B"], } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) if pre_sort: df = df.sort(aggs, **pre_sort) result = df.group_by(keys).agg(nw.col(aggs).last()).sort(keys) assert_equal_data(result, expected) -def test_multi_column_expansion(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 32): +def test_multi_column_expansion(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 32): pytest.skip(reason="https://github.com/pola-rs/polars/issues/21773") - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="Internal error") - df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = ( df.group_by("a") .agg(nw.all().sum().name.suffix("_aggregated")) diff --git a/tests/frame/head_test.py b/tests/frame/head_test.py index 7c1124485a..1c9aaf4123 100644 --- a/tests/frame/head_test.py +++ b/tests/frame/head_test.py @@ -4,11 +4,11 @@ from tests.utils import Constructor, assert_equal_data -def test_head(nw_frame_constructor: Constructor) -> None: +def test_head(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} expected = {"a": [1, 3], "b": [4, 4], "z": [7.0, 8.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.head(2) diff --git a/tests/frame/invalid_test.py b/tests/frame/invalid_test.py index 6253406a56..d59b67adb1 100644 --- a/tests/frame/invalid_test.py +++ b/tests/frame/invalid_test.py @@ -14,9 +14,9 @@ @pytest.mark.skipif( POLARS_VERSION < (1,), reason="Polars would raise unrecoverable panic." ) -def test_all_vs_all(nw_frame_constructor: Constructor) -> None: +def test_all_vs_all(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) with pytest.raises(MultiOutputExpressionError): df.lazy().select(nw.all() + nw.col("b", "a")).collect() diff --git a/tests/frame/is_duplicated_test.py b/tests/frame/is_duplicated_test.py index e644143525..0703d2bd6c 100644 --- a/tests/frame/is_duplicated_test.py +++ b/tests/frame/is_duplicated_test.py @@ -4,18 +4,18 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_is_duplicated(nw_eager_constructor: ConstructorEager) -> None: +def test_is_duplicated(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = nw.concat([df, df.head(1)]).is_duplicated() expected = {"is_duplicated": [True, False, False, True]} assert_equal_data({"is_duplicated": result}, expected) -def test_is_duplicated_with_nulls(nw_eager_constructor: ConstructorEager) -> None: +def test_is_duplicated_with_nulls(constructor_eager: ConstructorEager) -> None: data = {"col1": [1, 2, 3], "col2": ["one", None, None]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = df.is_duplicated() expected = {"is_duplicated": [False, False, False]} diff --git a/tests/frame/is_empty_test.py b/tests/frame/is_empty_test.py index 55f193d8a3..5464d0e678 100644 --- a/tests/frame/is_empty_test.py +++ b/tests/frame/is_empty_test.py @@ -12,10 +12,10 @@ @pytest.mark.parametrize(("threshold", "expected"), [(0, False), (10, True)]) def test_is_empty( - nw_eager_constructor: ConstructorEager, threshold: Any, expected: Any + constructor_eager: ConstructorEager, threshold: Any, expected: Any ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = df.filter(nw.col("a") > threshold).is_empty() assert result == expected diff --git a/tests/frame/is_unique_test.py b/tests/frame/is_unique_test.py index 1309b40a4b..10e9af910d 100644 --- a/tests/frame/is_unique_test.py +++ b/tests/frame/is_unique_test.py @@ -4,18 +4,18 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_is_unique(nw_eager_constructor: ConstructorEager) -> None: +def test_is_unique(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = nw.concat([df, df.head(1)]).is_unique() expected = {"is_unique": [False, True, True, False]} assert_equal_data({"is_unique": result}, expected) -def test_is_unique_with_nulls(nw_eager_constructor: ConstructorEager) -> None: +def test_is_unique_with_nulls(constructor_eager: ConstructorEager) -> None: data = {"col1": [1, 2, 3, 3], "col2": ["one", None, None, None]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = df.is_unique() expected = {"is_unique": [True, True, False, False]} diff --git a/tests/frame/item_test.py b/tests/frame/item_test.py index 4f319090a6..997b91d847 100644 --- a/tests/frame/item_test.py +++ b/tests/frame/item_test.py @@ -11,13 +11,13 @@ @pytest.mark.parametrize(("row", "column", "expected"), [(0, 2, 7), (1, "z", 8)]) def test_item( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, row: int | None, column: int | str | None, expected: Any, ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) assert_equal_data({"a": [df.item(row, column)]}, {"a": [expected]}) assert_equal_data({"a": [df.select("a").head(1).item()]}, {"a": [1]}) @@ -35,11 +35,11 @@ def test_item( ], ) def test_item_value_error( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, row: int | None, column: int | str | None, err_msg: str, ) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} with pytest.raises(ValueError, match=re.escape(err_msg)): - nw.from_native(nw_eager_constructor(data), eager_only=True).item(row, column) + nw.from_native(constructor_eager(data), eager_only=True).item(row, column) diff --git a/tests/frame/join_test.py b/tests/frame/join_test.py index 1f1604330f..7ca4754b2d 100644 --- a/tests/frame/join_test.py +++ b/tests/frame/join_test.py @@ -105,10 +105,10 @@ def test_full_join( on: None | str | list[str], left_on: None | str | list[str], right_on: None | str | list[str], - nw_frame_constructor: Constructor, + constructor: Constructor, ) -> None: - df_left = from_native_lazy(nw_frame_constructor(df1)) - df_right = from_native_lazy(nw_frame_constructor(df2)) + df_left = from_native_lazy(constructor(df1)) + df_right = from_native_lazy(constructor(df2)) result = df_left.join( df_right, on=on, left_on=left_on, right_on=right_on, how="full" ).sort("id", nulls_last=True) @@ -116,24 +116,22 @@ def test_full_join( def test_full_join_duplicate( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: - if "ibis" in str(nw_frame_constructor): + if "ibis" in str(constructor): request.applymarker(pytest.mark.xfail) df1 = {"foo": [1, 2, 3], "val1": [1, 2, 3]} df2 = {"foo": [1, 2, 3], "foo_right": [1, 2, 3]} - df_left = from_native_lazy(nw_frame_constructor(df1)) - df_right = from_native_lazy(nw_frame_constructor(df2)) + df_left = from_native_lazy(constructor(df1)) + df_right = from_native_lazy(constructor(df2)) exceptions: list[type[Exception]] = [nw.exceptions.NarwhalsError] - if "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( - nw_frame_constructor - ): + if "pyspark" in str(constructor) and "sqlframe" not in str(constructor): from pyspark.errors import AnalysisException exceptions.append(AnalysisException) - elif "cudf" in str(nw_frame_constructor): + elif "cudf" in str(constructor): # cudf throw their own exception earlier in the stack exceptions.append(ValueError) @@ -141,14 +139,14 @@ def test_full_join_duplicate( df_left.join(df_right, on="foo", how="full").collect() -def test_inner_join_two_keys(nw_frame_constructor: Constructor) -> None: +def test_inner_join_two_keys(constructor: Constructor) -> None: data = { "antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0], "idx": [0, 1, 2], } - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) df_right = df result = df.join( df_right, @@ -170,14 +168,14 @@ def test_inner_join_two_keys(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_on, expected) -def test_inner_join_single_key(nw_frame_constructor: Constructor) -> None: +def test_inner_join_single_key(constructor: Constructor) -> None: data = { "antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0], "idx": [0, 1, 2], } - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) df_right = df result = df.join( df_right, left_on="antananarivo", right_on="antananarivo", how="inner" @@ -197,11 +195,11 @@ def test_inner_join_single_key(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_on, expected) -def test_cross_join(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4): +def test_cross_join(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4): pytest.skip() data = {"antananarivo": [1, 3, 2]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) result = df.join(df, how="cross").sort("antananarivo", "antananarivo_right") expected = { "antananarivo": [1, 1, 1, 2, 2, 2, 3, 3, 3], @@ -218,10 +216,10 @@ def test_cross_join(nw_frame_constructor: Constructor) -> None: @pytest.mark.parametrize("how", ["inner", "left"]) @pytest.mark.parametrize("suffix", ["_right", "_custom_suffix"]) def test_suffix( - nw_frame_constructor: Constructor, how: Literal["inner", "left"], suffix: str + constructor: Constructor, how: Literal["inner", "left"], suffix: str ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) df_right = df result = df.join( df_right, @@ -235,11 +233,11 @@ def test_suffix( @pytest.mark.parametrize("suffix", ["_right", "_custom_suffix"]) -def test_cross_join_suffix(nw_frame_constructor: Constructor, suffix: str) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4): +def test_cross_join_suffix(constructor: Constructor, suffix: str) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4): pytest.skip() data = {"antananarivo": [1, 3, 2]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) result = df.join(df, how="cross", suffix=suffix).sort( "antananarivo", f"antananarivo{suffix}" ) @@ -283,13 +281,13 @@ def test_cross_join_non_pandas() -> None: # pragma: no cover ], ) def test_anti_join( - nw_frame_constructor: Constructor, + constructor: Constructor, join_key: list[str], filter_expr: nw.Expr, expected: dict[str, list[Any]], ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) other = df.filter(filter_expr) result = df.join(other, how="anti", left_on=join_key, right_on=join_key) assert_equal_data(result, expected) @@ -321,13 +319,13 @@ def test_anti_join( ], ) def test_semi_join( - nw_frame_constructor: Constructor, + constructor: Constructor, join_key: list[str], filter_expr: nw.Expr, expected: dict[str, list[Any]], ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) other = df.filter(filter_expr) result = df.join(other, how="semi", left_on=join_key, right_on=join_key).sort( "antananarivo" @@ -336,9 +334,9 @@ def test_semi_join( @pytest.mark.parametrize("how", ["right"]) -def test_join_not_implemented(nw_frame_constructor: Constructor, how: str) -> None: +def test_join_not_implemented(constructor: Constructor, how: str) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) with pytest.raises( NotImplementedError, @@ -354,7 +352,7 @@ def test_join_not_implemented(nw_frame_constructor: Constructor, how: str) -> No ) -def test_left_join(nw_frame_constructor: Constructor) -> None: +def test_left_join(constructor: Constructor) -> None: data_left = { "antananarivo": [1.0, 2.0, 3.0], "bob": [4.0, 5.0, 6.0], @@ -365,8 +363,8 @@ def test_left_join(nw_frame_constructor: Constructor) -> None: "co": [4.0, 5.0, 7.0], "idx": [0.0, 1.0, 2.0], } - df_left = from_native_lazy(nw_frame_constructor(data_left)) - df_right = from_native_lazy(nw_frame_constructor(data_right)) + df_left = from_native_lazy(constructor(data_left)) + df_right = from_native_lazy(constructor(data_right)) result = df_left.join(df_right, left_on="bob", right_on="co", how="left") result = result.sort("idx") result = result.drop("idx_right") @@ -388,11 +386,11 @@ def test_left_join(nw_frame_constructor: Constructor) -> None: assert_equal_data(result_on_list, expected_on_list) -def test_left_join_multiple_column(nw_frame_constructor: Constructor) -> None: +def test_left_join_multiple_column(constructor: Constructor) -> None: data_left = {"antananarivo": [1, 2, 3], "bob": [4, 5, 6], "idx": [0, 1, 2]} data_right = {"antananarivo": [1, 2, 3], "c": [4, 5, 6], "idx": [0, 1, 2]} - df_left = from_native_lazy(nw_frame_constructor(data_left)) - df_right = from_native_lazy(nw_frame_constructor(data_right)) + df_left = from_native_lazy(constructor(data_left)) + df_right = from_native_lazy(constructor(data_right)) result = df_left.join( df_right, left_on=["antananarivo", "bob"], @@ -405,7 +403,7 @@ def test_left_join_multiple_column(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_left_join_overlapping_column(nw_frame_constructor: Constructor) -> None: +def test_left_join_overlapping_column(constructor: Constructor) -> None: data_left = { "antananarivo": [1.0, 2.0, 3.0], "bob": [4.0, 5.0, 6.0], @@ -418,8 +416,8 @@ def test_left_join_overlapping_column(nw_frame_constructor: Constructor) -> None "d": [1.0, 4.0, 2.0], "idx": [0.0, 1.0, 2.0], } - df_left = from_native_lazy(nw_frame_constructor(data_left)) - df_right = from_native_lazy(nw_frame_constructor(data_right)) + df_left = from_native_lazy(constructor(data_left)) + df_right = from_native_lazy(constructor(data_right)) result = df_left.join(df_right, left_on="bob", right_on="c", how="left").sort("idx") result = result.drop("idx_right") expected: dict[str, list[Any]] = { @@ -446,11 +444,9 @@ def test_left_join_overlapping_column(nw_frame_constructor: Constructor) -> None @pytest.mark.parametrize("how", ["inner", "left", "semi", "anti"]) -def test_join_keys_exceptions( - nw_frame_constructor: Constructor, how: JoinStrategy -) -> None: +def test_join_keys_exceptions(constructor: Constructor, how: JoinStrategy) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) with pytest.raises( ValueError, @@ -501,31 +497,30 @@ def test_join_keys_exceptions( ], ) def test_joinasof_numeric( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, strategy: Literal["backward", "forward", "nearest"], expected: dict[str, list[Any]], ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if ( - "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor) + "duckdb" in str(constructor) or "ibis" in str(constructor) ) and strategy == "nearest": request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(nw_frame_constructor)) - or ("pandas_nullable" in str(nw_frame_constructor)) + ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) ): request.applymarker(pytest.mark.xfail) data_left = {"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]} data_right = {"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]} - left_lf = from_native_lazy(nw_frame_constructor(data_left)).sort("antananarivo") - right_lf = from_native_lazy(nw_frame_constructor(data_right)).sort("antananarivo") + left_lf = from_native_lazy(constructor(data_left)).sort("antananarivo") + right_lf = from_native_lazy(constructor(data_right)).sort("antananarivo") result: nw.DataFrame[Any] | nw.LazyFrame[Any] result_on: nw.DataFrame[Any] | nw.LazyFrame[Any] - if nw_frame_constructor.is_lazy: + if constructor.is_lazy: result = left_lf.join_asof( right_lf, left_on="antananarivo", right_on="antananarivo", strategy=strategy ) @@ -584,21 +579,21 @@ def test_joinasof_numeric( ], ) def test_joinasof_time( - nw_frame_constructor: Constructor, + constructor: Constructor, request: pytest.FixtureRequest, strategy: Literal["backward", "forward", "nearest"], expected: dict[str, list[Any]], ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if ( - "duckdb" in str(nw_frame_constructor) or "ibis" in str(nw_frame_constructor) + "duckdb" in str(constructor) or "ibis" in str(constructor) ) and strategy == "nearest": request.applymarker(pytest.mark.xfail) - if PANDAS_VERSION < (2, 1) and ("pandas_pyarrow" in str(nw_frame_constructor)): + if PANDAS_VERSION < (2, 1) and ("pandas_pyarrow" in str(constructor)): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - nw_frame_constructor( + constructor( { "datetime": [ datetime(2016, 3, 1), @@ -610,7 +605,7 @@ def test_joinasof_time( ) ).sort("datetime") df_right = from_native_lazy( - nw_frame_constructor( + constructor( { "datetime": [ datetime(2016, 1, 1), @@ -631,18 +626,15 @@ def test_joinasof_time( assert_equal_data(result_on.sort(by="datetime"), expected) -def test_joinasof_by( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): +def test_joinasof_by(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(nw_frame_constructor)) - or ("pandas_nullable" in str(nw_frame_constructor)) + ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) ): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - nw_frame_constructor( + constructor( { "antananarivo": [1, 5, 7, 10], "bob": ["D", "D", "C", "A"], @@ -651,7 +643,7 @@ def test_joinasof_by( ) ).sort("antananarivo") df_right = from_native_lazy( - nw_frame_constructor( + constructor( {"antananarivo": [1, 4, 5, 8], "bob": ["D", "D", "A", "F"], "d": [1, 3, 4, 1]} ) ).sort("antananarivo") @@ -668,20 +660,19 @@ def test_joinasof_by( def test_joinasof_suffix( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyarrow_table", "cudf", "pyspark")): + if any(x in str(constructor) for x in ("pyarrow_table", "cudf", "pyspark")): request.applymarker(pytest.mark.xfail) if PANDAS_VERSION < (2, 1) and ( - ("pandas_pyarrow" in str(nw_frame_constructor)) - or ("pandas_nullable" in str(nw_frame_constructor)) + ("pandas_pyarrow" in str(constructor)) or ("pandas_nullable" in str(constructor)) ): request.applymarker(pytest.mark.xfail) df = from_native_lazy( - nw_frame_constructor({"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]}) + constructor({"antananarivo": [1, 5, 10], "val": ["a", "b", "c"]}) ).sort("antananarivo") df_right = from_native_lazy( - nw_frame_constructor({"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]}) + constructor({"antananarivo": [1, 2, 3, 6, 7], "val": [1, 2, 3, 6, 7]}) ).sort("antananarivo") result = df.join_asof( df_right, left_on="antananarivo", right_on="antananarivo", suffix="_y" @@ -692,10 +683,10 @@ def test_joinasof_suffix( @pytest.mark.parametrize("strategy", ["back", "furthest"]) def test_joinasof_not_implemented( - nw_frame_constructor: Constructor, strategy: Literal["backward", "forward"] + constructor: Constructor, strategy: Literal["backward", "forward"] ) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) with pytest.raises( NotImplementedError, @@ -706,9 +697,9 @@ def test_joinasof_not_implemented( ) -def test_joinasof_keys_exceptions(nw_frame_constructor: Constructor) -> None: +def test_joinasof_keys_exceptions(constructor: Constructor) -> None: data = {"antananarivo": [1, 3, 2], "bob": [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - df = from_native_lazy(nw_frame_constructor(data)) + df = from_native_lazy(constructor(data)) with pytest.raises( ValueError, @@ -766,7 +757,7 @@ def test_joinasof_keys_exceptions(nw_frame_constructor: Constructor) -> None: ], ) def test_joinasof_by_exceptions( - nw_frame_constructor: Constructor, + constructor: Constructor, on: str | None, by_left: str | list[str] | None, by_right: str | list[str] | None, @@ -774,9 +765,9 @@ def test_joinasof_by_exceptions( message: str, ) -> None: data = {ON: [1, 3, 2], BY: [4, 4, 6], "zor ro": [7.0, 8.0, 9.0]} - frame = from_native_lazy(nw_frame_constructor(data)) + frame = from_native_lazy(constructor(data)) - if nw_frame_constructor.is_lazy: + if constructor.is_lazy: with pytest.raises(ValueError, match=message): frame.join_asof(frame, on=on, by_left=by_left, by_right=by_right, by=by) else: @@ -787,42 +778,40 @@ def test_joinasof_by_exceptions( def test_join_duplicate_column_names( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: exception: type[Exception] - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 26): + if "polars" in str(constructor) and POLARS_VERSION < (1, 26): pytest.skip() if ( - "cudf" in str(nw_frame_constructor) + "cudf" in str(constructor) # TODO(unassigned): cudf doesn't raise here for some reason, # need to investigate. ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3, 4, 5], "b": [6, 6, 6, 6, 6]} - lf = from_native_lazy(nw_frame_constructor(data)) + lf = from_native_lazy(constructor(data)) if any( - x in str(nw_frame_constructor) + x in str(constructor) for x in ("pandas", "pandas[pyarrow]", "pandas[nullable]", "dask") ) and PANDAS_VERSION >= (3,): # pragma: no cover from pandas.errors import MergeError exception = MergeError - elif "pyspark" in str(nw_frame_constructor) and "sqlframe" not in str( - nw_frame_constructor - ): + elif "pyspark" in str(constructor) and "sqlframe" not in str(constructor): from pyspark.errors import AnalysisException exception = AnalysisException - elif "modin" in str(nw_frame_constructor): + elif "modin" in str(constructor): exception = NotImplementedError - elif "ibis" in str(nw_frame_constructor): + elif "ibis" in str(constructor): # ibis doesn't raise here request.applymarker(pytest.mark.xfail) else: exception = nw.exceptions.DuplicateError - if nw_frame_constructor.is_lazy: + if constructor.is_lazy: with pytest.raises(exception): lf.join(lf, on=["a"]).join(lf, on=["a"]).collect() else: @@ -831,13 +820,13 @@ def test_join_duplicate_column_names( df.join(df, on=["a"]).join(df, on=["a"]) -def test_join_same_laziness(nw_frame_constructor: Constructor) -> None: +def test_join_same_laziness(constructor: Constructor) -> None: pytest.importorskip("polars") import polars as pl data_left = {"id": [1, 2, 3], "age": [25, 30, 35]} data_right = {"id": [2, 3, 4], "active": [False, True, True]} - frame = nw.from_native(nw_frame_constructor(data_left)) + frame = nw.from_native(constructor(data_left)) df_pl = pl.DataFrame(data_right) frame_pl: pl.DataFrame | pl.LazyFrame if isinstance(frame, nw.DataFrame): @@ -893,17 +882,17 @@ def test_join_same_laziness(nw_frame_constructor: Constructor) -> None: ], ) def test_join_on_null_values( - nw_frame_constructor: Constructor, how: JoinStrategy, expected: dict[str, list[Any]] + constructor: Constructor, how: JoinStrategy, expected: dict[str, list[Any]] ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 1, 4) and how=="cross": + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 1, 4) and how=="cross": pytest.skip() # See https://github.com/narwhals-dev/narwhals/issues/3307 keys = {"a": [1, 1, None, None], "b": [1, None, 5, None]} data_left = {**keys, "x": [1, 2, 3, 4]} data_right = {**keys, "y": [1.2, 3.4, 5.6, 7.8]} - df_left = from_native_lazy(nw_frame_constructor(data_left)) - df_right = from_native_lazy(nw_frame_constructor(data_right)) + df_left = from_native_lazy(constructor(data_left)) + df_right = from_native_lazy(constructor(data_right)) on = None if how == "cross" else list(keys) sort_by = ["a", "x", "y"] if how in {"cross", "full"} else ["a", "x"] @@ -916,7 +905,7 @@ def test_join_on_null_values( "ignore:.*Merging dataframes with merge column data type mismatches:UserWarning:dask" ) def test_full_join_with_overlapping_non_key_columns_and_nulls( - nw_frame_constructor: Constructor, + constructor: Constructor, ) -> None: data_left = { "id": [1, 2, 3], @@ -929,8 +918,8 @@ def test_full_join_with_overlapping_non_key_columns_and_nulls( "right_only": [100, 200, 300], } - df_left = from_native_lazy(nw_frame_constructor(data_left)) - df_right = from_native_lazy(nw_frame_constructor(data_right)) + df_left = from_native_lazy(constructor(data_left)) + df_right = from_native_lazy(constructor(data_right)) result = df_left.join(df_right, on="id", how="full", suffix="_r").sort( "id", nulls_last=True diff --git a/tests/frame/lazy_test.py b/tests/frame/lazy_test.py index 5507513cfd..658a61c68b 100644 --- a/tests/frame/lazy_test.py +++ b/tests/frame/lazy_test.py @@ -20,27 +20,27 @@ data = {"a": [1, 2, 3], "b": ["x", "y", "z"]} -def test_lazy_to_default(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_lazy_to_default(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.lazy() assert isinstance(result, nw.LazyFrame) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.lazy() assert isinstance(result, nw.LazyFrame) expected_cls: Any - if "polars" in str(nw_eager_constructor): + if "polars" in str(constructor_eager): import polars as pl expected_cls = pl.LazyFrame - elif "pandas" in str(nw_eager_constructor): + elif "pandas" in str(constructor_eager): import pandas as pd expected_cls = pd.DataFrame - elif "modin" in str(nw_eager_constructor): + elif "modin" in str(constructor_eager): mpd = get_modin() expected_cls = mpd.DataFrame - elif "cudf" in str(nw_eager_constructor): + elif "cudf" in str(constructor_eager): cudf = get_cudf() expected_cls = cudf.DataFrame else: # pyarrow @@ -70,21 +70,21 @@ def test_lazy_to_default(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_lazy( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, backend: LazyAllowed, request: pytest.FixtureRequest, ) -> None: impl = Implementation.from_backend(backend) pytest.importorskip(impl.name.lower()) if ( - "pandas_constructor" in str(nw_eager_constructor) + "pandas_constructor" in str(constructor_eager) and impl.is_duckdb() and PANDAS_VERSION >= (3,) and DUCKDB_VERSION < (1, 4, 4) ): # pragma: no cover # https://github.com/duckdb/duckdb/issues/18297 request.applymarker(pytest.mark.xfail) - if "pandas_nullable" in str(nw_eager_constructor): + if "pandas_nullable" in str(constructor_eager): pytest.importorskip("pyarrow") is_spark_connect = os.environ.get("SPARK_CONNECT", None) @@ -93,7 +93,7 @@ def test_lazy( # Implementation.PYSPARK_CONNECT, which is never installed. impl = Implementation.PYSPARK_CONNECT - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) session: Any if impl.is_sqlframe(): session = sqlframe_session() @@ -110,19 +110,19 @@ def test_lazy( @pytest.mark.parametrize("backend", ["pyspark", "sqlframe"]) def test_lazy_spark_like_requires_session( - nw_eager_constructor: ConstructorEager, backend: SparkLike + constructor_eager: ConstructorEager, backend: SparkLike ) -> None: impl = Implementation.from_backend(backend) pytest.importorskip(impl.name.lower()) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) err_msg = re.escape("Spark like backends require `session` to be not None.") with pytest.raises(ValueError, match=err_msg): df.lazy(backend=backend, session=None) -def test_lazy_backend_invalid(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) +def test_lazy_backend_invalid(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data), eager_only=True) with pytest.raises(ValueError, match="Not-supported backend"): df.lazy(backend=Implementation.PANDAS) # type: ignore[arg-type] diff --git a/tests/frame/len_test.py b/tests/frame/len_test.py index a63524c74a..3e709701c5 100644 --- a/tests/frame/len_test.py +++ b/tests/frame/len_test.py @@ -9,7 +9,7 @@ data = {"a": [1.0, 2.0, None, 4.0], "b": [None, 3.0, None, 5.0]} -def test_len(nw_eager_constructor: ConstructorEager) -> None: - result = len(nw.from_native(nw_eager_constructor(data), eager_only=True)) +def test_len(constructor_eager: ConstructorEager) -> None: + result = len(nw.from_native(constructor_eager(data), eager_only=True)) assert result == 4 diff --git a/tests/frame/null_count_test.py b/tests/frame/null_count_test.py index 99fc071814..eec6475c92 100644 --- a/tests/frame/null_count_test.py +++ b/tests/frame/null_count_test.py @@ -4,9 +4,9 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_null_count(nw_eager_constructor: ConstructorEager) -> None: +def test_null_count(constructor_eager: ConstructorEager) -> None: data = {"a": [None, 3, 2], "b": [4, 4, 6], "z": [7.0, None, 9]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw, eager_only=True) result = df.null_count() expected = {"a": [1], "b": [0], "z": [1]} diff --git a/tests/frame/pipe_test.py b/tests/frame/pipe_test.py index 0e38ebe2d8..0a2eac992d 100644 --- a/tests/frame/pipe_test.py +++ b/tests/frame/pipe_test.py @@ -6,8 +6,8 @@ data = {"a": ["foo", "bars"], "ab": ["foo", "bars"]} -def test_pipe(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_pipe(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) columns = df.collect_schema().names() result = df.pipe(lambda _df: _df.select([x for x in columns if len(x) == 2])) expected = {"ab": ["foo", "bars"]} diff --git a/tests/frame/pivot_test.py b/tests/frame/pivot_test.py index 67ace42095..260006555e 100644 --- a/tests/frame/pivot_test.py +++ b/tests/frame/pivot_test.py @@ -113,20 +113,20 @@ ) @pytest.mark.parametrize(("on", "index"), [("col", "ix"), (["col"], ["ix"])]) def test_pivot( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, agg_func: str, expected: dict[str, list[Any]], on: str | list[str], index: str | list[str], request: pytest.FixtureRequest, ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.pivot( on=on, index=index, @@ -146,15 +146,15 @@ def test_pivot( ], ) def test_pivot_no_agg( - request: Any, nw_eager_constructor: ConstructorEager, data_: Any, context: Any + request: Any, constructor_eager: ConstructorEager, data_: Any, context: Any ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_), eager_only=True) + df = nw.from_native(constructor_eager(data_), eager_only=True) with context: df.pivot("col", index="ix", aggregate_function=None) @@ -168,17 +168,17 @@ def test_pivot_no_agg( ) def test_pivot_sort_columns( request: Any, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, sort_columns: Any, expected: list[str], ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.pivot( on="col", index="ix", @@ -218,15 +218,15 @@ def test_pivot_sort_columns( ], ) def test_pivot_names_out( - request: Any, nw_eager_constructor: ConstructorEager, kwargs: Any, expected: list[str] + request: Any, constructor_eager: ConstructorEager, kwargs: Any, expected: list[str] ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = ( df.pivot(aggregate_function="min", index="ix", **kwargs).collect_schema().names() @@ -234,21 +234,21 @@ def test_pivot_names_out( assert result == expected -def test_pivot_no_index_no_values(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data_no_dups), eager_only=True) +def test_pivot_no_index_no_values(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data_no_dups), eager_only=True) with pytest.raises(ValueError, match="At least one of `values` and `index` must"): df.pivot(on="col") def test_pivot_no_index( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): # not implemented request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_no_dups), eager_only=True) + df = nw.from_native(constructor_eager(data_no_dups), eager_only=True) with pytest.warns(UserWarning, match="has no effect"): result = df.pivot(on="col", values="foo", maintain_order=True).sort("ix", "bar") expected = { diff --git a/tests/frame/rename_test.py b/tests/frame/rename_test.py index e0898d73b3..11ec77185c 100644 --- a/tests/frame/rename_test.py +++ b/tests/frame/rename_test.py @@ -4,9 +4,9 @@ from tests.utils import Constructor, assert_equal_data -def test_rename(nw_frame_constructor: Constructor) -> None: +def test_rename(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.rename({"a": "foo-bar", "b": "foo bar", "z": "z.b"}) expected = {"foo-bar": [1, 3, 2], "foo bar": [4, 4, 6], "z.b": [7.0, 8.0, 9.0]} assert_equal_data(result, expected) diff --git a/tests/frame/row_test.py b/tests/frame/row_test.py index e8ffbb54b7..186fbf3478 100644 --- a/tests/frame/row_test.py +++ b/tests/frame/row_test.py @@ -10,10 +10,10 @@ from tests.utils import ConstructorEager -def test_row_column(request: Any, nw_eager_constructor: ConstructorEager) -> None: - if "cudf" in str(nw_eager_constructor): +def test_row_column(request: Any, constructor_eager: ConstructorEager) -> None: + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 3.0, 4.0, 5.0, 6.0], "b": [11, 12, 13, 14, 15, 16]} - result = nw.from_native(nw_eager_constructor(data), eager_only=True).row(2) + result = nw.from_native(constructor_eager(data), eager_only=True).row(2) assert result == (3.0, 13) diff --git a/tests/frame/rows_test.py b/tests/frame/rows_test.py index 0a8851eed1..95fd2d8094 100644 --- a/tests/frame/rows_test.py +++ b/tests/frame/rows_test.py @@ -30,15 +30,15 @@ ) def test_iter_rows( request: Any, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = list(df.iter_rows(named=named)) assert result == expected @@ -61,11 +61,11 @@ def test_iter_rows( ], ) def test_rows( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.rows(named=named) assert result == expected @@ -88,24 +88,24 @@ def test_rows( ], ) def test_rows_eager( - nw_eager_constructor: Any, + constructor_eager: Any, named: bool, # noqa: FBT001 expected: list[tuple[Any, ...]] | list[dict[str, Any]], ) -> None: # posit-dev/py-shiny relies on `.rows(named=False)` to return unnamed rows data = {"a": [1, 3, 2], "_b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "1": [5, 6, 7]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.rows(named=named) assert result == expected def test_rows_with_nulls_unnamed( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # cudf intentionally doesn't support itertuples / iter_rows request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) + df = nw.from_native(constructor_eager(data_na), eager_only=True) result = list(df.iter_rows(named=False)) expected = [(None, 4, 7.0), (3, 4, None), (2, 6, 9.0)] for i, row in enumerate(expected): @@ -120,12 +120,12 @@ def test_rows_with_nulls_unnamed( def test_rows_with_nulls_named( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # cudf intentionally doesn't support itertuples / iter_rows request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_eager_constructor(data_na), eager_only=True) + df = nw.from_native(constructor_eager(data_na), eager_only=True) result = list(df.iter_rows(named=True)) expected: list[dict[str, Any]] = [ {"a": None, "b": 4, "z": 7.0}, diff --git a/tests/frame/sample_test.py b/tests/frame/sample_test.py index 46dbaa276f..b86ddaee1d 100644 --- a/tests/frame/sample_test.py +++ b/tests/frame/sample_test.py @@ -8,10 +8,9 @@ from tests.utils import ConstructorEager -def test_sample_n(nw_eager_constructor: ConstructorEager) -> None: +def test_sample_n(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), - eager_only=True, + constructor_eager({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), eager_only=True ) result_expr = df.sample(n=2).shape @@ -19,10 +18,9 @@ def test_sample_n(nw_eager_constructor: ConstructorEager) -> None: assert result_expr == expected_expr -def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: +def test_sample_fraction(constructor_eager: ConstructorEager) -> None: df = nw.from_native( - nw_eager_constructor({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), - eager_only=True, + constructor_eager({"a": [1, 2, 3, 4], "b": ["x", "y", "x", "y"]}), eager_only=True ) result_expr = df.sample(fraction=0.5).shape @@ -30,9 +28,9 @@ def test_sample_fraction(nw_eager_constructor: ConstructorEager) -> None: assert result_expr == expected_expr -def test_sample_with_seed(nw_eager_constructor: ConstructorEager) -> None: +def test_sample_with_seed(constructor_eager: ConstructorEager) -> None: size, n = 100, 10 - df = nw.from_native(nw_eager_constructor({"a": range(size)}), eager_only=True) + df = nw.from_native(constructor_eager({"a": range(size)}), eager_only=True) r1 = nw.to_native(df.sample(n=n, seed=123)) r2 = nw.to_native(df.sample(n=n, seed=123)) diff --git a/tests/frame/schema_test.py b/tests/frame/schema_test.py index 95214f695b..93779cd129 100644 --- a/tests/frame/schema_test.py +++ b/tests/frame/schema_test.py @@ -32,9 +32,9 @@ @pytest.mark.filterwarnings("ignore:Determining|Resolving.*") -def test_schema(nw_frame_constructor: Constructor) -> None: +def test_schema(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) + constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) ) result = df.schema expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64} @@ -45,9 +45,9 @@ def test_schema(nw_frame_constructor: Constructor) -> None: assert result == expected -def test_collect_schema(nw_frame_constructor: Constructor) -> None: +def test_collect_schema(constructor: Constructor) -> None: df = nw.from_native( - nw_frame_constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) + constructor({"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]}) ) expected = {"a": nw.Int64, "b": nw.Int64, "z": nw.Float64} @@ -83,15 +83,15 @@ def test_string_disguised_as_object() -> None: def test_actual_object( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "cudf")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "cudf")): request.applymarker(pytest.mark.xfail) class Foo: ... data = {"a": [Foo()]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.schema assert result == {"a": nw.Object} @@ -569,7 +569,7 @@ def origin_arrow( @pytest.fixture def origin_pandas_like( - nw_pandas_like_constructor: ConstructorPandasLike, + constructor_pandas_like: ConstructorPandasLike, ) -> IntoPandasSchema: data: dict[str, Any] = { "a": [2, 1], @@ -578,18 +578,18 @@ def origin_pandas_like( "d": [5.3, 4.99], "e": [datetime(2006, 1, 1), datetime(2001, 9, 3)], } - return nw_pandas_like_constructor(data).dtypes.to_dict() + return constructor_pandas_like(data).dtypes.to_dict() @pytest.fixture def origin_pandas_like_pyarrow( - nw_pandas_like_constructor: ConstructorPandasLike, + constructor_pandas_like: ConstructorPandasLike, ) -> IntoPandasSchema: if PANDAS_VERSION < (1, 5): pytest.skip(reason="pandas too old for `pyarrow`") name_pandas_like = {"pandas_pyarrow_constructor", "modin_pyarrow_constructor"} - if str(nw_pandas_like_constructor) not in name_pandas_like: - pytest.skip(f"{nw_pandas_like_constructor!s} is not pandas_like_pyarrow") + if str(constructor_pandas_like) not in name_pandas_like: + pytest.skip(f"{constructor_pandas_like!s} is not pandas_like_pyarrow") data = { "a": [2, 1], "b": ["hello", "hi"], @@ -599,7 +599,7 @@ def origin_pandas_like_pyarrow( "f": [date(2003, 1, 1), date(2004, 1, 1)], "g": [time(10, 1, 1), time(14, 1, 1)], } - df_pd = nw_pandas_like_constructor(data) + df_pd = constructor_pandas_like(data) df_nw = nw.from_native(df_pd).with_columns( nw.col("f").cast(nw.Date()), nw.col("g").cast(nw.Time()) ) diff --git a/tests/frame/select_test.py b/tests/frame/select_test.py index 7acb1d5cb6..ad8bce44f8 100644 --- a/tests/frame/select_test.py +++ b/tests/frame/select_test.py @@ -19,18 +19,16 @@ class Foo: ... -def test_select(nw_frame_constructor: Constructor) -> None: +def test_select(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select("a") expected = {"a": [1, 3, 2]} assert_equal_data(result, expected) -def test_empty_select(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native( - nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True - ).select() +def test_empty_select(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True).select() assert result.shape == (0, 0) @@ -54,9 +52,9 @@ def test_int_select_pandas() -> None: @pytest.mark.parametrize("invalid_select", [None, 0, Foo()]) -def test_invalid_select(nw_frame_constructor: Constructor, invalid_select: Any) -> None: +def test_invalid_select(constructor: Constructor, invalid_select: Any) -> None: with pytest.raises(InvalidIntoExprError): - nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})).select(invalid_select) + nw.from_native(constructor({"a": [1, 2, 3]})).select(invalid_select) def test_select_boolean_cols() -> None: @@ -101,7 +99,7 @@ def test_comparison_with_list_error_message() -> None: def test_missing_columns( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "ibis")): @@ -109,7 +107,7 @@ def test_missing_columns( request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) selected_columns = ["a", "e", "f"] if constructor_id == "polars[lazy]": @@ -142,12 +140,12 @@ def test_missing_columns( maybe_collect(df.select(nw.col("fdfa").sum())) -def test_left_to_right_broadcasting(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_left_to_right_broadcasting(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "dask" in str(nw_frame_constructor) and DASK_VERSION < (2024, 10): + if "dask" in str(constructor) and DASK_VERSION < (2024, 10): pytest.skip() - df = nw.from_native(nw_frame_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw.from_native(constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) result = df.select(nw.col("a") + nw.col("b").sum()) expected = {"a": [16, 16, 17]} assert_equal_data(result, expected) @@ -159,14 +157,14 @@ def test_left_to_right_broadcasting(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, expected) -def test_alias_invalid(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) +def test_alias_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) with pytest.raises((NarwhalsError, ValueError)): df.lazy().select(nw.all().alias("c")).collect() -def test_filtration_vs_aggregation(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, None, 3]})) +def test_filtration_vs_aggregation(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [1, None, 3]})) result = df.select(nw.col("a").drop_nulls(), b=nw.col("a").mean()) expected: dict[str, Any] = {"a": [1, 3], "b": [2.0, 2.0]} assert_equal_data(result, expected) @@ -175,11 +173,11 @@ def test_filtration_vs_aggregation(nw_eager_constructor: ConstructorEager) -> No assert_equal_data(result, expected) -def test_select_duplicates(nw_frame_constructor: Constructor) -> None: - if "cudf" in str(nw_frame_constructor): +def test_select_duplicates(constructor: Constructor) -> None: + if "cudf" in str(constructor): # cudf already raises its own error pytest.skip() - df = nw.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() + df = nw.from_native(constructor({"a": [1, 2]})).lazy() with pytest.raises( ValueError, match=r"Expected unique|[Dd]uplicate|more than one|Duplicate column name", @@ -187,8 +185,8 @@ def test_select_duplicates(nw_frame_constructor: Constructor) -> None: df.select("a", nw.col("a") + 1).collect() -def test_binary_window_aggregation(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 1, 2]})) +def test_binary_window_aggregation(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [1, 1, 2]})) result = df.select(nw.col("a").cum_sum() + nw.col("a").sum()) expected = {"a": [5, 6, 8]} assert_equal_data(result, expected) diff --git a/tests/frame/shape_test.py b/tests/frame/shape_test.py index 2637f20002..4a4cf710b9 100644 --- a/tests/frame/shape_test.py +++ b/tests/frame/shape_test.py @@ -8,9 +8,9 @@ from tests.utils import ConstructorEager -def test_shape(nw_eager_constructor: ConstructorEager) -> None: +def test_shape(constructor_eager: ConstructorEager) -> None: result = nw.from_native( - nw_eager_constructor({"a": [1, 2], "b": [4, 5], "c": [7, 8]}), eager_only=True + constructor_eager({"a": [1, 2], "b": [4, 5], "c": [7, 8]}), eager_only=True ).shape expected = (2, 3) assert result == expected diff --git a/tests/frame/sink_parquet_test.py b/tests/frame/sink_parquet_test.py index 29bc3f6d77..360828bded 100644 --- a/tests/frame/sink_parquet_test.py +++ b/tests/frame/sink_parquet_test.py @@ -16,12 +16,10 @@ @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") -def test_sink_parquet( - nw_frame_constructor: Constructor, tmpdir: pytest.TempdirFactory -) -> None: - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2, 0, 0): +def test_sink_parquet(constructor: Constructor, tmpdir: pytest.TempdirFactory) -> None: + if "pandas" in str(constructor) and PANDAS_VERSION < (2, 0, 0): pytest.skip(reason="too old for pyarrow") path = tmpdir / "foo.parquet" # type: ignore[operator] - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) df.lazy().sink_parquet(str(path)) assert path.exists() diff --git a/tests/frame/sort_test.py b/tests/frame/sort_test.py index 97436703f1..4539d90606 100644 --- a/tests/frame/sort_test.py +++ b/tests/frame/sort_test.py @@ -6,9 +6,9 @@ from tests.utils import Constructor, assert_equal_data -def test_sort(nw_frame_constructor: Constructor) -> None: +def test_sort(constructor: Constructor) -> None: data = {"an tan": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.sort("an tan", "b") expected = {"an tan": [1, 2, 3], "b": [4, 6, 4], "z": [7.0, 9.0, 8.0]} assert_equal_data(result, expected) @@ -25,9 +25,9 @@ def test_sort(nw_frame_constructor: Constructor) -> None: ], ) def test_sort_nulls( - nw_frame_constructor: Constructor, *, nulls_last: bool, expected: dict[str, float] + constructor: Constructor, *, nulls_last: bool, expected: dict[str, float] ) -> None: data = {"antan desc": [0, 0, 2, -1], "b": [1, 3, 2, None]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.sort("b", descending=True, nulls_last=nulls_last) assert_equal_data(result, expected) diff --git a/tests/frame/tail_test.py b/tests/frame/tail_test.py index 034ffd0783..4fdf4da8ef 100644 --- a/tests/frame/tail_test.py +++ b/tests/frame/tail_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_tail(nw_eager_constructor: ConstructorEager) -> None: +def test_tail(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} expected = {"a": [3, 2], "b": [4, 6], "z": [8.0, 9]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw) result = df.tail(2) assert_equal_data(result, expected) diff --git a/tests/frame/to_arrow_test.py b/tests/frame/to_arrow_test.py index 3a7b147556..3bb74a9dc7 100644 --- a/tests/frame/to_arrow_test.py +++ b/tests/frame/to_arrow_test.py @@ -14,9 +14,9 @@ @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") -def test_to_arrow(nw_eager_constructor: ConstructorEager) -> None: +def test_to_arrow(constructor_eager: ConstructorEager) -> None: data: dict[str, Any] = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) result = nw.from_native(df_raw, eager_only=True).to_arrow() expected = pa.table(data) diff --git a/tests/frame/to_dict_test.py b/tests/frame/to_dict_test.py index 0feb2e4938..c382a0619f 100644 --- a/tests/frame/to_dict_test.py +++ b/tests/frame/to_dict_test.py @@ -9,16 +9,16 @@ @pytest.mark.filterwarnings( "ignore:.*all arguments of to_dict except for the argument:FutureWarning" ) -def test_to_dict(nw_eager_constructor: ConstructorEager) -> None: +def test_to_dict(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.to_dict(as_series=False) assert result == data -def test_to_dict_as_series(nw_eager_constructor: ConstructorEager) -> None: +def test_to_dict_as_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "c": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = df.to_dict(as_series=True) assert isinstance(result["a"], nw.Series) assert isinstance(result["b"], nw.Series) diff --git a/tests/frame/to_native_test.py b/tests/frame/to_native_test.py index f96cd5d8bd..0ef0ae885a 100644 --- a/tests/frame/to_native_test.py +++ b/tests/frame/to_native_test.py @@ -8,9 +8,9 @@ from tests.utils import Constructor -def test_to_native(nw_frame_constructor: Constructor) -> None: +def test_to_native(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) assert isinstance(df.to_native(), df_raw.__class__) diff --git a/tests/frame/to_numpy_test.py b/tests/frame/to_numpy_test.py index 70c426c70b..9330a2c7b3 100644 --- a/tests/frame/to_numpy_test.py +++ b/tests/frame/to_numpy_test.py @@ -15,9 +15,9 @@ from tests.utils import ConstructorEager -def test_to_numpy(nw_eager_constructor: ConstructorEager) -> None: +def test_to_numpy(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) result = nw.from_native(df_raw, eager_only=True).to_numpy() expected = np.array([[1, 3, 2], [4, 4, 6], [7.1, 8.0, 9.0]]).T np.testing.assert_array_equal(result, expected) @@ -25,14 +25,14 @@ def test_to_numpy(nw_eager_constructor: ConstructorEager) -> None: def test_to_numpy_tz_aware( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) or ( - "pyarrow" in str(nw_eager_constructor) and is_windows() + if ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) or ( + "pyarrow" in str(constructor_eager) and is_windows() ): request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_eager_constructor({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), + constructor_eager({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), eager_only=True, ) df = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) diff --git a/tests/frame/to_pandas_test.py b/tests/frame/to_pandas_test.py index ca9ec2d673..b74c9a98b1 100644 --- a/tests/frame/to_pandas_test.py +++ b/tests/frame/to_pandas_test.py @@ -16,15 +16,15 @@ @pytest.mark.filterwarnings("ignore:.*Passing a BlockManager.*:DeprecationWarning") @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pandas-pyarrow") -def test_convert_pandas(nw_eager_constructor: ConstructorEager) -> None: +def test_convert_pandas(constructor_eager: ConstructorEager) -> None: pytest.importorskip("pyarrow") data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) result = nw.from_native(df_raw, eager_only=True).to_pandas() - if str(nw_eager_constructor).startswith("pandas"): - expected = cast("pd.DataFrame", nw_eager_constructor(data)) - elif "modin_pyarrow" in str(nw_eager_constructor): + if str(constructor_eager).startswith("pandas"): + expected = cast("pd.DataFrame", constructor_eager(data)) + elif "modin_pyarrow" in str(constructor_eager): expected = pd.DataFrame(data).convert_dtypes(dtype_backend="pyarrow") else: expected = pd.DataFrame(data) diff --git a/tests/frame/to_polars_test.py b/tests/frame/to_polars_test.py index d0faf59240..89d4a65b2a 100644 --- a/tests/frame/to_polars_test.py +++ b/tests/frame/to_polars_test.py @@ -15,12 +15,12 @@ @pytest.mark.filterwarnings("ignore:.*Passing a BlockManager.*:DeprecationWarning") -def test_convert_polars(nw_eager_constructor: ConstructorEager) -> None: +def test_convert_polars(constructor_eager: ConstructorEager) -> None: pytest.importorskip("pyarrow") from polars.testing import assert_frame_equal data: Data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.1, 8.0, 9.0]} - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) result = nw.from_native(df_raw).to_polars() expected = pl.DataFrame(data) diff --git a/tests/frame/top_k_test.py b/tests/frame/top_k_test.py index 6de02d7bfb..d0ba228df0 100644 --- a/tests/frame/top_k_test.py +++ b/tests/frame/top_k_test.py @@ -6,35 +6,35 @@ from tests.utils import DUCKDB_VERSION, POLARS_VERSION, Constructor, assert_equal_data -def test_top_k(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 0): +def test_top_k(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 0): # old polars versions do not sort nulls last pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": ["a", "f", "a", "d", "b", "c"], "b c": [None, None, 2, 3, 6, 1]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.top_k(4, by="b c") expected = {"a": ["a", "b", "c", "d"], "b c": [2, 6, 1, 3]} assert_equal_data(result.sort("a"), expected) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.top_k(4, by="b c", reverse=True) expected = {"a": ["a", "b", "c", "d"], "b c": [2, 6, 1, 3]} assert_equal_data(result.sort(by="a"), expected) -def test_top_k_by_multiple(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 22): +def test_top_k_by_multiple(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 22): # bug in old version pytest.skip() - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = { "a": ["a", "f", "a", "d", "b", "c"], "b": [2, 2, 2, 3, 1, 1], "sf_c": ["k", "d", "s", "a", "a", "r"], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.top_k(4, by=["b", "sf_c"], reverse=True) expected = { "a": ["b", "f", "a", "c"], @@ -47,7 +47,7 @@ def test_top_k_by_multiple(nw_frame_constructor: Constructor) -> None: "b": [2, 2, 2, 3, 1, 1], "sf_c": ["k", "d", "s", "a", "a", "r"], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.top_k(4, by=["b", "sf_c"], reverse=[False, True]) expected = { "a": ["d", "f", "a", "a"], diff --git a/tests/frame/unique_test.py b/tests/frame/unique_test.py index 26a22cebd2..691540d0a2 100644 --- a/tests/frame/unique_test.py +++ b/tests/frame/unique_test.py @@ -20,12 +20,12 @@ ], ) def test_unique_eager( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, subset: str | list[str] | None, keep: Literal["first", "last"], expected: dict[str, list[float]], ) -> None: - df_raw = nw_eager_constructor(data) + df_raw = constructor_eager(data) df = nw.from_native(df_raw) result = df.unique(subset, keep=keep).sort("z") assert_equal_data(result, expected) @@ -39,18 +39,18 @@ def test_unique_eager( ], ) def test_unique_first_last( - nw_frame_constructor: Constructor, + constructor: Constructor, keep: Literal["first", "last"], expected: dict[str, list[float]], request: pytest.FixtureRequest, ) -> None: - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/12073 request.applymarker(pytest.mark.xfail) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"i": [0, 1, None, 2], "a": [1, 3, 2, 1], "b": [4, 4, 4, 6]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.unique("b", keep=keep, order_by="i").sort("i") assert_equal_data(result, expected) @@ -68,14 +68,14 @@ def test_unique_first_last( ], ) def test_unique_first_last_no_subset( - nw_frame_constructor: Constructor, + constructor: Constructor, keep: Literal["first", "last"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"i": [0, 1, 1, 2], "b": [4, 4, 4, 6]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.unique(keep=keep, order_by="i").sort("i") assert_equal_data(result, expected) @@ -85,10 +85,10 @@ def test_unique_first_last_no_subset( assert_equal_data(result, expected) -def test_unique_invalid(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_invalid(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) with pytest.raises(ColumnNotFoundError): df.lazy().unique(["fdssfad"]).collect() @@ -104,13 +104,13 @@ def test_unique_invalid(nw_frame_constructor: Constructor) -> None: ], ) def test_unique( - nw_frame_constructor: Constructor, + constructor: Constructor, keep: Literal["any", "none"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.unique(["b"], keep=keep).sort("z") assert_equal_data(result, expected) @@ -122,30 +122,30 @@ def test_unique( [("any", {"a": [1, 1, 2], "b": [3, 4, 4]}), ("none", {"a": [1, 2], "b": [4, 4]})], ) def test_unique_full_subset( - nw_frame_constructor: Constructor, + constructor: Constructor, subset: list[str] | None, keep: Literal["any", "none"], expected: dict[str, list[float]], ) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": [1, 1, 1, 2], "b": [3, 3, 4, 4]} - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.unique(subset, keep=keep).sort("a", "b") assert_equal_data(result, expected) -def test_unique_invalid_keep(nw_frame_constructor: Constructor) -> None: +def test_unique_invalid_keep(constructor: Constructor) -> None: with pytest.raises(ValueError, match=r"(Got|got): cabbage"): - nw.from_native(nw_frame_constructor(data)).unique(keep="cabbage") # type: ignore[arg-type] + nw.from_native(constructor(data)).unique(keep="cabbage") # type: ignore[arg-type] @pytest.mark.filterwarnings("ignore:.*backwards-compatibility:UserWarning") -def test_unique_none(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_none(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - df_raw = nw_frame_constructor(data) + df_raw = constructor(data) df = nw.from_native(df_raw) result = df.unique().sort("z") @@ -156,11 +156,11 @@ def test_unique_none(nw_frame_constructor: Constructor) -> None: assert_equal_data(result, data) -def test_unique_3069(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_unique_3069(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"name": ["a", "b", "c"], "group": ["d", "e", "f"], "value": [1, 2, 3]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) unique_to_get = "group" result = df.select(nw.col(unique_to_get)).unique().sort(unique_to_get) expected = {"group": ["d", "e", "f"]} diff --git a/tests/frame/unpivot_test.py b/tests/frame/unpivot_test.py index 66e2283382..8d661ae1de 100644 --- a/tests/frame/unpivot_test.py +++ b/tests/frame/unpivot_test.py @@ -49,12 +49,12 @@ ], ) def test_unpivot( - nw_frame_constructor: Constructor, + constructor: Constructor, on: str | list[str] | None, index: list[str] | None, expected: dict[str, list[float]], ) -> None: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) sort_columns = ["variable"] if index is None else ["variable", "a"] result = df.unpivot(on=on, index=index).sort(by=sort_columns) assert_equal_data(result, expected) @@ -69,24 +69,24 @@ def test_unpivot( ], ) def test_unpivot_var_value_names( - nw_frame_constructor: Constructor, variable_name: str, value_name: str + constructor: Constructor, variable_name: str, value_name: str ) -> None: context = ( pytest.raises(NotImplementedError) if ( any([variable_name == "", value_name == ""]) and ( - "duckdb" in str(nw_frame_constructor) + "duckdb" in str(constructor) # This might depend from the dialect we use in sqlframe. # Since for now we use only duckdb, we need to xfail it - or "sqlframe" in str(nw_frame_constructor) + or "sqlframe" in str(constructor) ) ) else does_not_raise() ) with context: - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.unpivot( on=["b", "c"], index=["a"], variable_name=variable_name, value_name=value_name ) @@ -94,8 +94,8 @@ def test_unpivot_var_value_names( assert result.collect_schema().names()[-2:] == [variable_name, value_name] -def test_unpivot_default_var_value_names(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_unpivot_default_var_value_names(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.unpivot(on=["b", "c"], index=["a"]) assert result.collect_schema().names()[-2:] == ["variable", "value"] @@ -112,16 +112,16 @@ def test_unpivot_default_var_value_names(nw_frame_constructor: Constructor) -> N ) def test_unpivot_mixed_types( request: pytest.FixtureRequest, - nw_frame_constructor: Constructor, + constructor: Constructor, data: dict[str, Any], expected_dtypes: list[DType], ) -> None: - if "cudf" in str(nw_frame_constructor) or ( - "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (14, 0, 0) + if "cudf" in str(constructor) or ( + "pyarrow_table" in str(constructor) and PYARROW_VERSION < (14, 0, 0) ): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.unpivot(on=["a", "b"], index="idx") assert result.collect_schema().dtypes() == expected_dtypes diff --git a/tests/frame/with_columns_sequence_test.py b/tests/frame/with_columns_sequence_test.py index a74adcffc2..106f473886 100644 --- a/tests/frame/with_columns_sequence_test.py +++ b/tests/frame/with_columns_sequence_test.py @@ -11,9 +11,9 @@ data = {"a": ["foo", "bars"], "ab": ["foo", "bars"]} -def test_with_columns(nw_eager_constructor: ConstructorEager) -> None: +def test_with_columns(constructor_eager: ConstructorEager) -> None: result = ( - nw.from_native(nw_eager_constructor(data)) + nw.from_native(constructor_eager(data)) .with_columns(d=np.array([4, 5])) # pyright: ignore[reportArgumentType] .with_columns(e=nw.col("d") + 1) .select("d", "e") diff --git a/tests/frame/with_columns_test.py b/tests/frame/with_columns_test.py index 36de016c25..e2325e9347 100644 --- a/tests/frame/with_columns_test.py +++ b/tests/frame/with_columns_test.py @@ -28,34 +28,34 @@ def test_with_columns_int_col_name_pandas() -> None: pd.testing.assert_frame_equal(result, expected) -def test_with_columns_order(nw_frame_constructor: Constructor) -> None: +def test_with_columns_order(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1) assert result.collect_schema().names() == ["a", "b", "z", "d"] expected = {"a": [2, 4, 3], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "d": [0, 2, 1]} assert_equal_data(result, expected) -def test_with_columns_empty(nw_eager_constructor: ConstructorEager) -> None: +def test_with_columns_empty(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df.select().with_columns() assert_equal_data(result, {}) -def test_select_with_columns_empty_lazy(nw_frame_constructor: Constructor) -> None: +def test_select_with_columns_empty_lazy(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df = nw.from_native(nw_frame_constructor(data)).lazy() + df = nw.from_native(constructor(data)).lazy() with pytest.raises(ValueError, match="At least one"): df.with_columns() with pytest.raises(ValueError, match="At least one"): df.select() -def test_with_columns_order_single_row(nw_frame_constructor: Constructor) -> None: +def test_with_columns_order_single_row(constructor: Constructor) -> None: data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0], "i": [0, 1, 2]} - df = nw.from_native(nw_frame_constructor(data)).filter(nw.col("i") < 1).drop("i") + df = nw.from_native(constructor(data)).filter(nw.col("i") < 1).drop("i") result = df.with_columns(nw.col("a") + 1, d=nw.col("a") - 1) assert result.collect_schema().names() == ["a", "b", "z", "d"] expected = {"a": [2], "b": [4], "z": [7.0], "d": [0]} @@ -63,46 +63,42 @@ def test_with_columns_order_single_row(nw_frame_constructor: Constructor) -> Non def test_with_columns_dtypes_single_row( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pyarrow_table" in str(nw_frame_constructor) and PYARROW_VERSION < (15,): + if "pyarrow_table" in str(constructor) and PYARROW_VERSION < (15,): pytest.skip() if ( - ("pyspark" in str(nw_frame_constructor)) - or "duckdb" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + ("pyspark" in str(constructor)) + or "duckdb" in str(constructor) + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) data = {"a": ["foo"]} - df = nw.from_native(nw_frame_constructor(data)).with_columns( - nw.col("a").cast(nw.Categorical) - ) + df = nw.from_native(constructor(data)).with_columns(nw.col("a").cast(nw.Categorical)) result = df.with_columns(nw.col("a")) assert result.collect_schema() == {"a": nw.Categorical} -def test_with_columns_series_shape_mismatch( - nw_eager_constructor: ConstructorEager, -) -> None: - df1 = nw.from_native(nw_eager_constructor({"first": [1, 2, 3]}), eager_only=True) - second = nw.from_native( - nw_eager_constructor({"second": [1, 2, 3, 4]}), eager_only=True - )["second"] +def test_with_columns_series_shape_mismatch(constructor_eager: ConstructorEager) -> None: + df1 = nw.from_native(constructor_eager({"first": [1, 2, 3]}), eager_only=True) + second = nw.from_native(constructor_eager({"second": [1, 2, 3, 4]}), eager_only=True)[ + "second" + ] with pytest.raises(ShapeError): df1.with_columns(second=second) def test_with_columns_missing_column( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: constructor_id = str(request.node.callspec.id) if any(id_ == constructor_id for id_ in ("sqlframe", "ibis")): # `sqlframe` raises a different error depending on its underlying backend request.applymarker(pytest.mark.xfail) data = {"a": [1, 2], "b": [3, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) - if "polars" in str(nw_frame_constructor): + if "polars" in str(constructor): msg = r"c" elif any(id_ == constructor_id for id_ in ("duckdb", "pyspark")): msg = r"\n\nHint: Did you mean one of these columns: \['a', 'b'\]?" diff --git a/tests/frame/with_row_index_test.py b/tests/frame/with_row_index_test.py index 32251a024d..10310ca7f6 100644 --- a/tests/frame/with_row_index_test.py +++ b/tests/frame/with_row_index_test.py @@ -20,8 +20,8 @@ data = {"abc": ["foo", "bars"], "xyz": [100, 200], "const": [42, 42]} -def test_with_row_index_eager(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native(nw_eager_constructor(data), eager_only=True).with_row_index() +def test_with_row_index_eager(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager(data), eager_only=True).with_row_index() expected = {"index": [0, 1], **data} assert_equal_data(result, expected) @@ -36,24 +36,20 @@ def test_with_row_index_eager(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_with_row_index_lazy( - nw_frame_constructor: Constructor, - order_by: str | Sequence[str], - expected_index: list[int], + constructor: Constructor, order_by: str | Sequence[str], expected_index: list[int] ) -> None: if ( - "pandas" in str(nw_frame_constructor) - and PANDAS_VERSION < (1, 3) - and order_by == "abc" + "pandas" in str(constructor) and PANDAS_VERSION < (1, 3) and order_by == "abc" ): # pragma: no cover reason = "ValueError: first not supported for non-numeric data." pytest.skip(reason=reason) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() result = ( - nw.from_native(nw_frame_constructor(data)) + nw.from_native(constructor(data)) .with_row_index(name="foo bar", order_by=order_by) .sort("xyz") ) @@ -61,8 +57,8 @@ def test_with_row_index_lazy( assert_equal_data(result, expected) -def test_with_row_index_lazy_exception(nw_frame_constructor: Constructor) -> None: - frame = nw.from_native(nw_frame_constructor(data)) +def test_with_row_index_lazy_exception(constructor: Constructor) -> None: + frame = nw.from_native(constructor(data)) msg = r"(LazyFrame\.)?with_row_index\(\) missing 1 required keyword-only argument: 'order_by'$" if isinstance(frame, nw.LazyFrame): with pytest.raises(TypeError, match=msg): @@ -82,21 +78,18 @@ def test_with_row_index_lazy_exception(nw_frame_constructor: Constructor) -> Non ], ) def test_with_row_index_lazy_meaner_examples( - nw_frame_constructor: Constructor, order_by: list[str], expected_index: list[int] + constructor: Constructor, order_by: list[str], expected_index: list[int] ) -> None: # https://github.com/narwhals-dev/narwhals/issues/3289 - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor) and POLARS_VERSION < (1, 10): pytest.skip() - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < ( - 1, - 3, - ): # pragma: no cover + if "pandas" in str(constructor) and PANDAS_VERSION < (1, 3): # pragma: no cover reason = "ValueError: first not supported for non-numeric data." pytest.skip(reason=reason) - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"a": ["A", "B", "A"], "b": [1, 2, 3], "c": [9, 2, 4]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.with_row_index(name="index", order_by=order_by).sort("b") expected = {"index": expected_index, **data} assert_equal_data(result, expected) diff --git a/tests/frame/write_csv_test.py b/tests/frame/write_csv_test.py index 945051cb47..5f907ac78c 100644 --- a/tests/frame/write_csv_test.py +++ b/tests/frame/write_csv_test.py @@ -10,19 +10,17 @@ def test_write_csv( - nw_eager_constructor: ConstructorEager, tmpdir: pytest.TempdirFactory + constructor_eager: ConstructorEager, tmpdir: pytest.TempdirFactory ) -> None: data = {"a": [1, 2, 3]} path = tmpdir / "foo.csv" # type: ignore[operator] - result = nw.from_native(nw_eager_constructor(data), eager_only=True).write_csv( - str(path) - ) + result = nw.from_native(constructor_eager(data), eager_only=True).write_csv(str(path)) assert path.exists() assert result is None - result = nw.from_native(nw_eager_constructor(data), eager_only=True).write_csv() + result = nw.from_native(constructor_eager(data), eager_only=True).write_csv() if is_windows(): # pragma: no cover result = result.replace("\r\n", "\n") - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): assert result == '"a"\n1\n2\n3\n' else: assert result == "a\n1\n2\n3\n" diff --git a/tests/frame/write_parquet_test.py b/tests/frame/write_parquet_test.py index 69443245b3..cf86f1be00 100644 --- a/tests/frame/write_parquet_test.py +++ b/tests/frame/write_parquet_test.py @@ -17,8 +17,8 @@ @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pyarrow") @pytest.mark.filterwarnings("ignore:.*is_sparse is deprecated:DeprecationWarning") def test_write_parquet( - nw_eager_constructor: ConstructorEager, tmpdir: pytest.TempdirFactory + constructor_eager: ConstructorEager, tmpdir: pytest.TempdirFactory ) -> None: path = tmpdir / "foo.parquet" # type: ignore[operator] - nw.from_native(nw_eager_constructor(data), eager_only=True).write_parquet(str(path)) + nw.from_native(constructor_eager(data), eager_only=True).write_parquet(str(path)) assert path.exists() diff --git a/tests/from_dict_test.py b/tests/from_dict_test.py index c89b4a0fc6..93ea5b2880 100644 --- a/tests/from_dict_test.py +++ b/tests/from_dict_test.py @@ -36,14 +36,12 @@ def test_from_dict_schema(eager_backend: EagerAllowed) -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) -def test_from_dict_without_backend( - nw_frame_constructor: Constructor, backend: Polars -) -> None: +def test_from_dict_without_backend(constructor: Constructor, backend: Polars) -> None: pytest.importorskip("polars") pytest.importorskip("pyarrow") df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) @@ -51,12 +49,8 @@ def test_from_dict_without_backend( assert_equal_data(result, {"c": [1, 2, 3], "d": [4, 5, 6]}) -def test_from_dict_without_backend_invalid(nw_frame_constructor: Constructor) -> None: - df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) - .lazy() - .collect() - ) +def test_from_dict_without_backend_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})).lazy().collect() with pytest.raises(TypeError, match="backend"): nw.from_dict({"c": nw.to_native(df["a"]), "d": nw.to_native(df["b"])}) @@ -69,13 +63,13 @@ def test_from_dict_with_backend_invalid() -> None: @pytest.mark.parametrize("backend", [Implementation.POLARS, "polars"]) def test_from_dict_one_native_one_narwhals( - nw_frame_constructor: Constructor, backend: Polars + constructor: Constructor, backend: Polars ) -> None: pytest.importorskip("pyarrow") pytest.importorskip("polars") df = ( - nw.from_native(nw_frame_constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) + nw.from_native(constructor({"a": [1, 2, 3], "b": [4, 5, 6]})) .lazy() .collect(backend=backend) ) diff --git a/tests/from_numpy_test.py b/tests/from_numpy_test.py index b66ee738a6..e8ebcbc6f0 100644 --- a/tests/from_numpy_test.py +++ b/tests/from_numpy_test.py @@ -23,32 +23,32 @@ } -def test_from_numpy(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_from_numpy(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend) assert_equal_data(result, expected) assert isinstance(result, nw.DataFrame) -def test_from_numpy_schema_dict(nw_eager_constructor: ConstructorEager) -> None: +def test_from_numpy_schema_dict(constructor_eager: ConstructorEager) -> None: schema = {"c": nw.Int16(), "d": nw.Float32(), "e": nw.Int16(), "f": nw.Float64()} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend, schema=schema) assert result.collect_schema() == schema -def test_from_numpy_schema_list(nw_eager_constructor: ConstructorEager) -> None: +def test_from_numpy_schema_list(constructor_eager: ConstructorEager) -> None: schema = ["c", "d", "e", "f"] - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) backend = nw.get_native_namespace(df) result = nw.from_numpy(arr, backend=backend, schema=schema) assert result.columns == schema -def test_from_numpy_schema_notvalid(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_from_numpy_schema_notvalid(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) backend = nw.get_native_namespace(df) with pytest.raises(TypeError, match=r"`schema.*expected.*types"): nw.from_numpy(arr, schema=5, backend=backend) # type: ignore[arg-type] @@ -60,8 +60,8 @@ def test_from_numpy_non_eager() -> None: nw.from_numpy(arr, backend="duckdb") # type: ignore[arg-type] -def test_from_numpy_not2d(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor(data)) +def test_from_numpy_not2d(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager(data)) backend = nw.get_native_namespace(df) with pytest.raises(ValueError, match="`from_numpy` only accepts 2D numpy arrays"): nw.from_numpy(np.array([0]), backend=backend) # pyright: ignore[reportArgumentType] diff --git a/tests/joblib_test.py b/tests/joblib_test.py index 23060aa66c..72b9440544 100644 --- a/tests/joblib_test.py +++ b/tests/joblib_test.py @@ -12,12 +12,12 @@ from joblib import Parallel, delayed -def test_parallelisability(nw_eager_constructor: ConstructorEager) -> None: +def test_parallelisability(constructor_eager: ConstructorEager) -> None: # https://github.com/narwhals-dev/narwhals/issues/2450 def do_something(df: nw.DataFrame[Any]) -> nw.DataFrame[Any]: # pragma: no cover return df.with_columns(nw.col("col1") * 2) - dfs = [nw.from_native(nw_eager_constructor({"col1": [0, 2], "col2": [3, 7]}))] + dfs = [nw.from_native(constructor_eager({"col1": [0, 2], "col2": [3, 7]}))] result = list(Parallel(n_jobs=-1)(delayed(do_something)(df_) for df_ in dfs)) assert len(result) == 1 expected = {"col1": [0, 4], "col2": [3, 7]} @@ -25,10 +25,10 @@ def do_something(df: nw.DataFrame[Any]) -> nw.DataFrame[Any]: # pragma: no cove def test_parallelisability_series( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: # https://github.com/narwhals-dev/narwhals/issues/2450 - if "modin" in str(nw_eager_constructor): + if "modin" in str(constructor_eager): request.applymarker(pytest.mark.xfail) def do_something(s: nw.Series[Any]) -> nw.Series[Any]: # pragma: no cover @@ -36,7 +36,7 @@ def do_something(s: nw.Series[Any]) -> nw.Series[Any]: # pragma: no cover columns = [ nw.from_native( - nw_eager_constructor({"col1": [0, 2], "col2": [3, 7]}), eager_only=True + constructor_eager({"col1": [0, 2], "col2": [3, 7]}), eager_only=True )["col1"] ] result = list( diff --git a/tests/modern_polars/ewm_mean_test.py b/tests/modern_polars/ewm_mean_test.py index 2d2ebcadd2..0b3ea06923 100644 --- a/tests/modern_polars/ewm_mean_test.py +++ b/tests/modern_polars/ewm_mean_test.py @@ -7,11 +7,11 @@ def test_ew_mean( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table_", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table_", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() data = { @@ -41,7 +41,7 @@ def test_ew_mean( ], } - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) expr = ( nw.col("close") diff --git a/tests/modern_polars/filter_test.py b/tests/modern_polars/filter_test.py index 82e1c01c3b..a6a0664cf8 100644 --- a/tests/modern_polars/filter_test.py +++ b/tests/modern_polars/filter_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, assert_equal_data -def test_filter(nw_frame_constructor: Constructor) -> None: +def test_filter(constructor: Constructor) -> None: data = { "time": [ "2021-01-01", @@ -34,7 +34,7 @@ def test_filter(nw_frame_constructor: Constructor) -> None: ], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) df = df.with_columns(nw.col("time").str.to_datetime(format="%Y-%m-%d")) diff --git a/tests/modern_polars/method_chaining_2_test.py b/tests/modern_polars/method_chaining_2_test.py index bcd1d3f0a1..58451e9f9a 100644 --- a/tests/modern_polars/method_chaining_2_test.py +++ b/tests/modern_polars/method_chaining_2_test.py @@ -27,8 +27,8 @@ } -def test_filter_is_between(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_filter_is_between(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = ( df.select(nw.col(["flight_date", "tail_number", "dep_time", "dep_delay"])) .drop_nulls() diff --git a/tests/modern_polars/method_chaining_test.py b/tests/modern_polars/method_chaining_test.py index 9f36e32409..ba7a06b894 100644 --- a/tests/modern_polars/method_chaining_test.py +++ b/tests/modern_polars/method_chaining_test.py @@ -30,24 +30,20 @@ } -def test_split_list_get( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(backend in str(nw_frame_constructor) for backend in ("dask",)): +def test_split_list_get(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(backend in str(constructor) for backend in ("dask",)): request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_frame_constructor): + if "pandas" in str(constructor): if PANDAS_VERSION < (2, 2): pytest.skip() pytest.importorskip("pyarrow") - if str(nw_frame_constructor).startswith("pandas") and "pyarrow" not in str( - nw_frame_constructor - ): - df = nw.from_native(nw_frame_constructor(data)) + if str(constructor).startswith("pandas") and "pyarrow" not in str(constructor): + df = nw.from_native(constructor(data)) msg = re.escape("This operation requires a pyarrow-backed series. ") with pytest.raises(TypeError, match=msg): df.select(nw.col("OriginCityName").str.split(",").list.get(0)) return - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(nw.col("OriginCityName").str.split(",").list.get(0)) assert_equal_data(result, expected) diff --git a/tests/modern_polars/performance_test.py b/tests/modern_polars/performance_test.py index 04686aaad4..b765055cbd 100644 --- a/tests/modern_polars/performance_test.py +++ b/tests/modern_polars/performance_test.py @@ -10,12 +10,10 @@ expected = {"weight_kg": [89, 38, 79, 68, 78, 33, 86]} -def test_parse_weight( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if any(x in str(nw_frame_constructor) for x in ("pyspark", "ibis", "duckdb")): +def test_parse_weight(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if any(x in str(constructor) for x in ("pyspark", "ibis", "duckdb")): request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) col = nw.col("weight") is_kg = col.str.ends_with("kg") diff --git a/tests/modern_polars/pivot_test.py b/tests/modern_polars/pivot_test.py index c481258a02..b6e6b16dde 100644 --- a/tests/modern_polars/pivot_test.py +++ b/tests/modern_polars/pivot_test.py @@ -9,11 +9,11 @@ def test_pivot( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if any(x in str(nw_eager_constructor) for x in ("pyarrow_table", "modin")): + if any(x in str(constructor_eager) for x in ("pyarrow_table", "modin")): request.applymarker(pytest.mark.xfail) - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 0): + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 0): pytest.skip() data = { @@ -25,7 +25,7 @@ def test_pivot( "ticker": [*["AAPL", "TSLA", "MSFT", "NFLX"] * 3], "price": [100, 200, 300, 400, 110, 220, 330, 420, 105, 210, 315, 440], } - df = nw.from_native(nw_eager_constructor(data), eager_only=True).sort("date") + df = nw.from_native(constructor_eager(data), eager_only=True).sort("date") pivoted = df.pivot(index="date", values="price", on="ticker") diff --git a/tests/modern_polars/unpivot_test.py b/tests/modern_polars/unpivot_test.py index 69105641ea..c5bff87dc6 100644 --- a/tests/modern_polars/unpivot_test.py +++ b/tests/modern_polars/unpivot_test.py @@ -6,7 +6,7 @@ from tests.utils import Constructor, assert_equal_data -def test_unpivot(nw_frame_constructor: Constructor) -> None: +def test_unpivot(constructor: Constructor) -> None: data = { "date": [datetime(2020, 1, 1), datetime(2020, 1, 2), datetime(2020, 1, 3)], "aapl": [110, 100, 105], @@ -14,7 +14,7 @@ def test_unpivot(nw_frame_constructor: Constructor) -> None: "msft": [330, 300, 315], "nflx": [420, 400, 440], } - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.unpivot(index="date", value_name="price").sort(by=["date", "variable"]) expected = { "date": [ diff --git a/tests/namespace_test.py b/tests/namespace_test.py index ebb2ec9d17..e94a6690c1 100644 --- a/tests/namespace_test.py +++ b/tests/namespace_test.py @@ -70,9 +70,9 @@ def test_namespace_from_backend_name(backend: BackendName) -> None: assert namespace.version is Version.MAIN -def test_namespace_from_native_object(nw_frame_constructor: Constructor) -> None: +def test_namespace_from_native_object(constructor: Constructor) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6]} - frame = nw_frame_constructor(data) + frame = constructor(data) namespace = Namespace.from_native_object(frame) nw_frame = nw.from_native(frame) assert namespace.implementation == nw_frame.implementation diff --git a/tests/new_series_test.py b/tests/new_series_test.py index 0aa33418f9..9360ef6fdc 100644 --- a/tests/new_series_test.py +++ b/tests/new_series_test.py @@ -6,8 +6,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_new_series(nw_eager_constructor: ConstructorEager) -> None: - s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] +def test_new_series(constructor_eager: ConstructorEager) -> None: + s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] result = nw.new_series("b", [4, 1, 2], backend=nw.get_native_namespace(s)) expected = {"b": [4, 1, 2]} # all supported libraries auto-infer this to be int64, we can always special-case diff --git a/tests/preserve_pandas_like_columns_name_attr_test.py b/tests/preserve_pandas_like_columns_name_attr_test.py index fec4d018a7..3127040bee 100644 --- a/tests/preserve_pandas_like_columns_name_attr_test.py +++ b/tests/preserve_pandas_like_columns_name_attr_test.py @@ -11,20 +11,18 @@ def test_ops_preserve_column_index_name( - nw_frame_constructor: Callable[..., pd.DataFrame], request: pytest.FixtureRequest + constructor: Callable[..., pd.DataFrame], request: pytest.FixtureRequest ) -> None: - if not any( - x in str(nw_frame_constructor) for x in ("pandas", "modin", "cudf", "dask") - ): + if not any(x in str(constructor) for x in ("pandas", "modin", "cudf", "dask")): pytest.skip( reason="Dataframe columns is a list and do not have a `name` like a pandas Index does" ) - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): # https://github.com/dask/dask/issues/11874 request.applymarker(pytest.mark.xfail) data = {"a": [1, 3, 2], "b": [4, 4, 6], "z": [7.0, 8.0, 9.0]} - df_native = nw_frame_constructor(data) + df_native = constructor(data) df_native.columns.name = "foo" df = nw.from_native(df_native) diff --git a/tests/read_scan_test.py b/tests/read_scan_test.py index a0439aa88b..0e0c94d994 100644 --- a/tests/read_scan_test.py +++ b/tests/read_scan_test.py @@ -126,16 +126,16 @@ def test_read_csv_raise_with_lazy(backend: _LazyOnly) -> None: def test_scan_csv( - csv_path: FileSource, csv_path_sep: FileSource, nw_frame_constructor: Constructor + csv_path: FileSource, csv_path_sep: FileSource, constructor: Constructor ) -> None: kwargs: dict[str, Any] - if "sqlframe" in str(nw_frame_constructor): + if "sqlframe" in str(constructor): kwargs = {"session": sqlframe_session(), "inferSchema": True, "header": True} - elif "pyspark" in str(nw_frame_constructor): + elif "pyspark" in str(constructor): kwargs = {"session": pyspark_session(), "inferSchema": True, "header": True} else: kwargs = {} - backend = native_namespace(nw_frame_constructor) + backend = native_namespace(constructor) assert_equal_lazy(nw.scan_csv(csv_path, backend=backend, **kwargs)) assert_equal_lazy(nw.scan_csv(csv_path_sep, backend=backend, separator="|", **kwargs)) @@ -171,17 +171,15 @@ def test_read_parquet_raise_with_lazy(backend: _LazyOnly) -> None: @skipif_pandas_lt_1_5 -def test_scan_parquet( - parquet_path: FileSource, nw_frame_constructor: Constructor -) -> None: +def test_scan_parquet(parquet_path: FileSource, constructor: Constructor) -> None: kwargs: dict[str, Any] - if "sqlframe" in str(nw_frame_constructor): + if "sqlframe" in str(constructor): kwargs = {"session": sqlframe_session(), "inferSchema": True} - elif "pyspark" in str(nw_frame_constructor): + elif "pyspark" in str(constructor): kwargs = {"session": pyspark_session(), "inferSchema": True, "header": True} else: kwargs = {} - backend = native_namespace(nw_frame_constructor) + backend = native_namespace(constructor) assert_equal_lazy(nw.scan_parquet(parquet_path, backend=backend, **kwargs)) diff --git a/tests/selectors_test.py b/tests/selectors_test.py index 9cb7f153c4..63c6b387e5 100644 --- a/tests/selectors_test.py +++ b/tests/selectors_test.py @@ -27,79 +27,73 @@ data_regex = {"foo": ["x", "y"], "bar": [123, 456], "baz": [2.0, 5.5], "zap": [0, 1]} -def test_selectors(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_selectors(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(ncs.by_dtype([nw.Int64, nw.Float64]) + 1) expected = {"a": [2, 2, 3], "c": [5.1, 6.0, 7.0]} assert_equal_data(result, expected) -def test_matches(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data_regex)) +def test_matches(constructor: Constructor) -> None: + df = nw.from_native(constructor(data_regex)) result = df.select(ncs.matches("[^z]a") + 1) expected = {"bar": [124, 457], "baz": [3.0, 6.5]} assert_equal_data(result, expected) -def test_numeric(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_numeric(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(ncs.numeric() + 1) expected = {"a": [2, 2, 3], "c": [5.1, 6.0, 7.0]} assert_equal_data(result, expected) -def test_boolean(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_boolean(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(ncs.boolean()) expected = {"d": [True, False, True]} assert_equal_data(result, expected) -def test_string(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_string(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) result = df.select(ncs.string()) expected = {"b": ["a", "b", "c"]} assert_equal_data(result, expected) -def test_categorical( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor -) -> None: - if "pyarrow_table_constructor" in str(nw_frame_constructor) and PYARROW_VERSION <= ( +def test_categorical(request: pytest.FixtureRequest, constructor: Constructor) -> None: + if "pyarrow_table_constructor" in str(constructor) and PYARROW_VERSION <= ( 15, ): # pragma: no cover request.applymarker(pytest.mark.xfail) if ( - "pyspark" in str(nw_frame_constructor) - or "duckdb" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + "pyspark" in str(constructor) + or "duckdb" in str(constructor) + or "ibis" in str(constructor) ): request.applymarker(pytest.mark.xfail) expected = {"b": ["a", "b", "c"]} - df = nw.from_native(nw_frame_constructor(data)).with_columns( - nw.col("b").cast(nw.Categorical) - ) + df = nw.from_native(constructor(data)).with_columns(nw.col("b").cast(nw.Categorical)) result = df.select(ncs.categorical()) assert_equal_data(result, expected) -def test_datetime( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: +def test_datetime(constructor: Constructor, request: pytest.FixtureRequest) -> None: if ( - "pyspark" in str(nw_frame_constructor) - or "duckdb" in str(nw_frame_constructor) - or "dask" in str(nw_frame_constructor) - or ("pyarrow" in str(nw_frame_constructor) and is_windows()) - or ("pandas" in str(nw_frame_constructor) and PANDAS_VERSION < (2,)) - or "ibis" in str(nw_frame_constructor) + "pyspark" in str(constructor) + or "duckdb" in str(constructor) + or "dask" in str(constructor) + or ("pyarrow" in str(constructor) and is_windows()) + or ("pandas" in str(constructor) and PANDAS_VERSION < (2,)) + or "ibis" in str(constructor) # https://github.com/pola-rs/polars/issues/23767 # TODO(FBruzzesi): Manage polars version - or ("polars" in str(nw_frame_constructor) and POLARS_VERSION >= (1, 32, 0)) + or ("polars" in str(constructor) and POLARS_VERSION >= (1, 32, 0)) ): request.applymarker(pytest.mark.xfail) - if "modin" in str(nw_frame_constructor): + if "modin" in str(constructor): pytest.skip(reason="too slow") ts1 = datetime(2000, 11, 20, 18, 12, 16, 600000) @@ -108,7 +102,7 @@ def test_datetime( data = {"numeric": [3.14, 6.28], "ts": [ts1, ts2]} time_units: list[Literal["ns", "us", "ms", "s"]] = ["ms", "us", "ns"] - df = nw.from_native(nw_frame_constructor(data)).select( + df = nw.from_native(constructor(data)).select( nw.col("numeric"), *[ nw.col("ts").cast(nw.Datetime(time_unit=tu)).alias(f"ts_{tu}") @@ -190,13 +184,13 @@ def test_datetime( ).collect_schema().names() == ["ts_ms", "ts_us", "ts_utc"] -def test_datetime_no_tz(nw_frame_constructor: Constructor) -> None: +def test_datetime_no_tz(constructor: Constructor) -> None: ts1 = datetime(2000, 11, 20, 18, 12, 16, 600000) ts2 = datetime(2020, 10, 30, 10, 20, 25, 123000) data = {"numeric": [3.14, 6.28], "ts": [ts1, ts2]} - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) assert df.select(ncs.datetime()).collect_schema().names() == ["ts"] @@ -215,36 +209,36 @@ def test_datetime_no_tz(nw_frame_constructor: Constructor) -> None: ], ) def test_set_ops( - nw_frame_constructor: Constructor, + constructor: Constructor, selector: nw.selectors.Selector, expected: list[str], request: pytest.FixtureRequest, ) -> None: if ( - any(x in str(nw_frame_constructor) for x in ("duckdb", "sqlframe", "ibis")) + any(x in str(constructor) for x in ("duckdb", "sqlframe", "ibis")) and not expected ): # https://github.com/narwhals-dev/narwhals/issues/2469 request.applymarker(pytest.mark.xfail) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(selector).collect_schema().names() assert sorted(result) == expected -def test_subtract_expr(nw_frame_constructor: Constructor) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (0, 20, 27): +def test_subtract_expr(constructor: Constructor) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (0, 20, 27): # In old Polars versions, cs.numeric() - col('a') # would exclude column 'a' from the result, as opposed to # subtracting it. pytest.skip() - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) result = df.select(ncs.numeric() - nw.col("a")) expected = {"a": [0, 0, 0], "c": [3.1, 4.0, 4.0]} assert_equal_data(result, expected) -def test_set_ops_invalid(nw_frame_constructor: Constructor) -> None: - df = nw.from_native(nw_frame_constructor(data)) +def test_set_ops_invalid(constructor: Constructor) -> None: + df = nw.from_native(constructor(data)) with pytest.raises((NotImplementedError, ValueError)): df.select(1 - ncs.numeric()) with pytest.raises((NotImplementedError, ValueError)): @@ -260,22 +254,20 @@ def test_set_ops_invalid(nw_frame_constructor: Constructor) -> None: @pytest.mark.skipif(is_windows(), reason="windows is what it is") -def test_tz_aware( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "polars" in str(nw_frame_constructor) and POLARS_VERSION < (1, 19): +def test_tz_aware(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "polars" in str(constructor) and POLARS_VERSION < (1, 19): # bug in old polars pytest.skip() if ( - "duckdb" in str(nw_frame_constructor) - or "pyspark" in str(nw_frame_constructor) - or "ibis" in str(nw_frame_constructor) + "duckdb" in str(constructor) + or "pyspark" in str(constructor) + or "ibis" in str(constructor) ): # replace_time_zone not implemented request.applymarker(pytest.mark.xfail) data = {"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)], "c": [4, 5]} - df = nw.from_native(nw_frame_constructor(data)).with_columns( + df = nw.from_native(constructor(data)).with_columns( b=nw.col("a").dt.replace_time_zone("Asia/Katmandu") ) result = df.select(nw.selectors.by_dtype(nw.Datetime)).collect_schema().names() diff --git a/tests/series_only/__contains___test.py b/tests/series_only/__contains___test.py index 6829192afb..13bc0eb4e0 100644 --- a/tests/series_only/__contains___test.py +++ b/tests/series_only/__contains___test.py @@ -17,25 +17,25 @@ ("other", "expected"), [(100, True), (None, True), (1, False), (100.314, False)] ) def test_contains( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, other: int | None, expected: bool, # noqa: FBT001 ) -> None: - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] assert (other in s) == expected @pytest.mark.parametrize("other", ["foo", [1, 2, 3]]) def test_contains_invalid_type( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager, other: Any + request: pytest.FixtureRequest, constructor_eager: ConstructorEager, other: Any ) -> None: - if "polars" not in str(nw_eager_constructor) and "pyarrow_table" not in str( - nw_eager_constructor + if "polars" not in str(constructor_eager) and "pyarrow_table" not in str( + constructor_eager ): request.applymarker(pytest.mark.xfail) - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] with pytest.raises(InvalidOperationError): _ = other in s diff --git a/tests/series_only/__iter___test.py b/tests/series_only/__iter___test.py index b00e6b18f8..5ed9e083f9 100644 --- a/tests/series_only/__iter___test.py +++ b/tests/series_only/__iter___test.py @@ -15,11 +15,11 @@ def test_iter( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] assert isinstance(s, Iterable) assert_equal_data({"a": [x for x in s]}, {"a": [1, 2, 3]}) # noqa: C416 diff --git a/tests/series_only/alias_rename_test.py b/tests/series_only/alias_rename_test.py index 8ed8e8c657..e8420e8089 100644 --- a/tests/series_only/alias_rename_test.py +++ b/tests/series_only/alias_rename_test.py @@ -4,10 +4,10 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_alias_rename(nw_eager_constructor: ConstructorEager) -> None: +def test_alias_rename(constructor_eager: ConstructorEager) -> None: data = [1, 2, 3] expected = {"bar": data} - series = nw.from_native(nw_eager_constructor({"foo": data}), eager_only=True)["foo"] + series = nw.from_native(constructor_eager({"foo": data}), eager_only=True)["foo"] result = series.alias("bar").to_frame() assert_equal_data(result, expected) result = series.rename("bar").to_frame() diff --git a/tests/series_only/arg_max_test.py b/tests/series_only/arg_max_test.py index 8bbc41a048..c6460b7183 100644 --- a/tests/series_only/arg_max_test.py +++ b/tests/series_only/arg_max_test.py @@ -10,18 +10,18 @@ @pytest.mark.parametrize(("col", "expected"), [("a", 1), ("b", 2), ("z", 2)]) def test_arg_max_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, col: str, expected: float, request: pytest.FixtureRequest, ) -> None: - if "modin" in str(nw_eager_constructor): + if "modin" in str(constructor_eager): # TODO(unassigned): bug in modin? return - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # not implemented yet request.applymarker(pytest.mark.xfail) - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] series = nw.maybe_set_index(series, index=[1, 0, 9]) # type: ignore[arg-type] result = series.arg_max() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/series_only/arg_min_test.py b/tests/series_only/arg_min_test.py index 6e2b91e7ac..34a38a57f9 100644 --- a/tests/series_only/arg_min_test.py +++ b/tests/series_only/arg_min_test.py @@ -10,18 +10,18 @@ @pytest.mark.parametrize(("col", "expected"), [("a", 0), ("b", 0), ("z", 0)]) def test_arg_min_series( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, col: str, expected: float, request: pytest.FixtureRequest, ) -> None: - if "modin" in str(nw_eager_constructor): + if "modin" in str(constructor_eager): # TODO(unassigned): bug in modin? return - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # not implemented yet request.applymarker(pytest.mark.xfail) - series = nw.from_native(nw_eager_constructor(data), eager_only=True)[col] + series = nw.from_native(constructor_eager(data), eager_only=True)[col] series = nw.maybe_set_index(series, index=[1, 0, 9]) # type: ignore[arg-type] result = series.arg_min() assert_equal_data({col: [result]}, {col: [expected]}) diff --git a/tests/series_only/arg_true_test.py b/tests/series_only/arg_true_test.py index 70dbad5e2a..ccc25a83e7 100644 --- a/tests/series_only/arg_true_test.py +++ b/tests/series_only/arg_true_test.py @@ -4,8 +4,8 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_arg_true_series(nw_eager_constructor: ConstructorEager) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, None, None, 3]}), eager_only=True) +def test_arg_true_series(constructor_eager: ConstructorEager) -> None: + df = nw.from_native(constructor_eager({"a": [1, None, None, 3]}), eager_only=True) result = df.select(df["a"].is_null().arg_true()) expected = {"a": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/series_only/array_dunder_test.py b/tests/series_only/array_dunder_test.py index 57ed6db5e4..b50d033aa2 100644 --- a/tests/series_only/array_dunder_test.py +++ b/tests/series_only/array_dunder_test.py @@ -15,49 +15,49 @@ def test_array_dunder( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__() np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype="int64")) def test_array_dunder_with_dtype( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__(object) np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype=object)) def test_array_dunder_with_copy( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 16, 0, 0, ): # pragma: no cover request.applymarker(pytest.mark.xfail) - s = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + s = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] result = s.__array__(copy=True) np.testing.assert_array_equal(result, np.array([1, 2, 3], dtype="int64")) - if "pandas_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < (3,): + if "pandas_constructor" in str(constructor_eager) and PANDAS_VERSION < (3,): # If it's pandas, we know that `copy=False` definitely took effect. # So, let's check it! result = s.__array__(copy=False) diff --git a/tests/series_only/cast_test.py b/tests/series_only/cast_test.py index 3db0300bf9..b646f38299 100644 --- a/tests/series_only/cast_test.py +++ b/tests/series_only/cast_test.py @@ -13,12 +13,12 @@ def test_cast_253( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): request.applymarker(pytest.mark.xfail) - df_raw = nw_eager_constructor({"a": [1]}) + df_raw = constructor_eager({"a": [1]}) result = nw.from_native(df_raw, eager_only=True).select( nw.col("a").cast(nw.String) + "hi" )["a"][0] @@ -111,16 +111,16 @@ def test_unknown_to_int() -> None: def test_cast_to_enum_vmain( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: # Backends that do not (yet) support Enum dtype if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("pyarrow_table", "sqlframe", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - df_nw = nw.from_native(nw_frame_constructor({"a": ["a", "b"]})) + df_nw = nw.from_native(constructor({"a": ["a", "b"]})) col_a = nw.col("a") with pytest.raises( diff --git a/tests/series_only/gather_every_test.py b/tests/series_only/gather_every_test.py index 11fe56702a..e7d55fb03c 100644 --- a/tests/series_only/gather_every_test.py +++ b/tests/series_only/gather_every_test.py @@ -11,9 +11,9 @@ @pytest.mark.parametrize("n", [1, 2, 3]) @pytest.mark.parametrize("offset", [1, 2, 3]) def test_gather_every_series( - nw_eager_constructor: ConstructorEager, n: int, offset: int + constructor_eager: ConstructorEager, n: int, offset: int ) -> None: - series = nw.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw.from_native(constructor_eager(data), eager_only=True)["a"] result = series.gather_every(n=n, offset=offset) expected = data["a"][offset::n] diff --git a/tests/series_only/getitem_test.py b/tests/series_only/getitem_test.py index ec62dcda27..aa63ac8414 100644 --- a/tests/series_only/getitem_test.py +++ b/tests/series_only/getitem_test.py @@ -11,9 +11,9 @@ from tests.utils import ConstructorEager -def test_by_slice(nw_eager_constructor: ConstructorEager) -> None: +def test_by_slice(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 2, 3], "b": [4, 5, 6], "c": [7, 8, 9], "d": [1, 4, 2]} - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) result = {"a": df["a"][[0, 1]]} expected = {"a": [1, 2]} assert_equal_data(result, expected) @@ -51,8 +51,8 @@ def test_getitem_arrow_scalar() -> None: assert isinstance(result, int) -def test_index(nw_eager_constructor: ConstructorEager) -> None: - df = nw_eager_constructor({"a": [0, 1, 2]}) +def test_index(constructor_eager: ConstructorEager) -> None: + df = constructor_eager({"a": [0, 1, 2]}) snw = nw.from_native(df, eager_only=True)["a"] assert snw[snw[0]] == 0 @@ -60,17 +60,17 @@ def test_index(nw_eager_constructor: ConstructorEager) -> None: @pytest.mark.filterwarnings( "ignore:.*_array__ implementation doesn't accept a copy keyword.*:DeprecationWarning:modin" ) -def test_getitem_other_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native( - nw_eager_constructor({"a": [1, None, 2, 3]}), eager_only=True - )["a"] - other = nw.from_native(nw_eager_constructor({"b": [1, 3]}), eager_only=True)["b"] +def test_getitem_other_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager({"a": [1, None, 2, 3]}), eager_only=True)[ + "a" + ] + other = nw.from_native(constructor_eager({"b": [1, 3]}), eager_only=True)["b"] assert_equal_data(series[other].to_frame(), {"a": [None, 3]}) -def test_getitem_invalid_series(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native( - nw_eager_constructor({"a": [1, None, 2, 3]}), eager_only=True - )["a"] +def test_getitem_invalid_series(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager({"a": [1, None, 2, 3]}), eager_only=True)[ + "a" + ] with pytest.raises(TypeError, match="Unexpected type"): series[series > 1] diff --git a/tests/series_only/head_test.py b/tests/series_only/head_test.py index e273245c54..5697bc59e5 100644 --- a/tests/series_only/head_test.py +++ b/tests/series_only/head_test.py @@ -7,8 +7,8 @@ @pytest.mark.parametrize("n", [2, -1]) -def test_head_series(nw_eager_constructor: ConstructorEager, n: int) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) +def test_head_series(constructor_eager: ConstructorEager, n: int) -> None: + df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) result = df.select(df["a"].head(n)) expected = {"a": [1, 2]} assert_equal_data(result, expected) diff --git a/tests/series_only/hist_test.py b/tests/series_only/hist_test.py index d75ed388a6..882c658f27 100644 --- a/tests/series_only/hist_test.py +++ b/tests/series_only/hist_test.py @@ -77,8 +77,8 @@ def maybe_name_to_constructor(name: str) -> ConstructorEager: def test_hist_bin( name: str, bins: list[float], expected: Sequence[float], *, include_breakpoint: bool ) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) - df = nw.from_native(nw_eager_constructor(data)).with_columns( + constructor_eager = maybe_name_to_constructor(name) + df = nw.from_native(constructor_eager(data)).with_columns( float=nw.col("int").cast(nw.Float64) ) expected_full = {"count": expected} @@ -106,7 +106,7 @@ def test_hist_bin( # missing/nan results df = nw.from_native( - nw_eager_constructor( + constructor_eager( {"has_nan": [float("nan"), *data["int"]], "has_null": [None, *data["int"]]} ) ) @@ -124,8 +124,8 @@ def test_hist_bin( def test_hist_count( name: str, *, params: dict[str, Any], include_breakpoint: bool ) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) - df = nw.from_native(nw_eager_constructor(data)).with_columns( + constructor_eager = maybe_name_to_constructor(name) + df = nw.from_native(constructor_eager(data)).with_columns( float=nw.col("int").cast(nw.Float64) ) bin_count = params["bin_count"] @@ -148,7 +148,7 @@ def test_hist_count( # missing/nan results df = nw.from_native( - nw_eager_constructor( + constructor_eager( {"has_nan": [float("nan"), *data["int"]], "has_null": [None, *data["int"]]} ) ) @@ -167,9 +167,9 @@ def test_hist_count( @param_name def test_hist_count_no_spread(name: str) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) + constructor_eager = maybe_name_to_constructor(name) data = {"all_zero": [0, 0, 0], "all_non_zero": [5, 5, 5]} - df = nw.from_native(nw_eager_constructor(data)) + df = nw.from_native(constructor_eager(data)) result = df["all_zero"].hist(bin_count=4, include_breakpoint=True) expected = {"breakpoint": [-0.25, 0.0, 0.25, 0.5], "count": [0, 3, 0, 0]} @@ -199,8 +199,8 @@ def test_hist_bin_and_bin_count() -> None: @param_include_breakpoint @param_name def test_hist_no_data(name: str, *, include_breakpoint: bool) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) - s = nw.from_native(nw_eager_constructor({"values": []})).select( + constructor_eager = maybe_name_to_constructor(name) + s = nw.from_native(constructor_eager({"values": []})).select( nw.col("values").cast(nw.Float64) )["values"] for bin_count in [1, 10]: @@ -221,8 +221,8 @@ def test_hist_no_data(name: str, *, include_breakpoint: bool) -> None: @param_name def test_hist_small_bins(name: str) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) - s = nw.from_native(nw_eager_constructor({"values": [1, 2, 3]})) + constructor_eager = maybe_name_to_constructor(name) + s = nw.from_native(constructor_eager({"values": [1, 2, 3]})) result = s["values"].hist(bins=None, bin_count=None) assert len(result) == 10 @@ -230,11 +230,11 @@ def test_hist_small_bins(name: str) -> None: s["values"].hist(bins=[1, 3], bin_count=4) -def test_hist_non_monotonic(nw_eager_constructor: ConstructorEager) -> None: - if "cudf" in str(nw_eager_constructor): +def test_hist_non_monotonic(constructor_eager: ConstructorEager) -> None: + if "cudf" in str(constructor_eager): # TODO(unassigned): too many spurious failures, report and revisit return - df = nw.from_native(nw_eager_constructor({"int": [0, 1, 2, 3, 4, 5, 6]})) + df = nw.from_native(constructor_eager({"int": [0, 1, 2, 3, 4, 5, 6]})) with pytest.raises(ComputeError, match="monotonic"): df["int"].hist(bins=[5, 0, 2]) @@ -275,14 +275,14 @@ def test_hist_non_monotonic(nw_eager_constructor: ConstructorEager) -> None: def test_hist_bin_hypotheis( name: str, data: list[float], bin_deltas: list[float] ) -> None: - nw_eager_constructor = maybe_name_to_constructor(name) + constructor_eager = maybe_name_to_constructor(name) pytest.importorskip("polars") import polars as pl - df = nw.from_native(nw_eager_constructor({"values": data})).select( + df = nw.from_native(constructor_eager({"values": data})).select( nw.col("values").cast(nw.Float64) ) - df_bins_native = nw_eager_constructor({"bins": bin_deltas}) + df_bins_native = constructor_eager({"bins": bin_deltas}) bins = ( nw.from_native(df_bins_native, eager_only=True) .get_column("bins") @@ -319,8 +319,8 @@ def test_hist_count_hypothesis( pytest.importorskip("polars") import polars as pl - nw_eager_constructor = maybe_name_to_constructor(name) - df = nw.from_native(nw_eager_constructor({"values": data})).select( + constructor_eager = maybe_name_to_constructor(name) + df = nw.from_native(constructor_eager({"values": data})).select( nw.col("values").cast(nw.Float64) ) @@ -344,7 +344,7 @@ def test_hist_count_hypothesis( if expected[ "count" ].sum() != expected_data.is_not_nan().sum() and "polars" not in str( - nw_eager_constructor + constructor_eager ): request.applymarker(pytest.mark.xfail) diff --git a/tests/series_only/is_empty_test.py b/tests/series_only/is_empty_test.py index 17d1408c05..cfdc8bd15d 100644 --- a/tests/series_only/is_empty_test.py +++ b/tests/series_only/is_empty_test.py @@ -8,8 +8,8 @@ from tests.utils import ConstructorEager -def test_is_empty(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] +def test_is_empty(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] assert not series.is_empty() assert not series[:1].is_empty() assert len(series[:1]) == 1 diff --git a/tests/series_only/is_ordered_categorical_test.py b/tests/series_only/is_ordered_categorical_test.py index fd49cfd7b0..8833957b1c 100644 --- a/tests/series_only/is_ordered_categorical_test.py +++ b/tests/series_only/is_ordered_categorical_test.py @@ -70,10 +70,10 @@ def test_is_ordered_categorical_pyarrow_string() -> None: def test_is_definitely_not_ordered_categorical( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, ) -> None: assert not nw.is_ordered_categorical( - nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] ) diff --git a/tests/series_only/is_sorted_test.py b/tests/series_only/is_sorted_test.py index 7a1723425e..4efddf542f 100644 --- a/tests/series_only/is_sorted_test.py +++ b/tests/series_only/is_sorted_test.py @@ -15,20 +15,18 @@ [(data, False, False), (data_sorted, False, True), (data_sorted, True, False)], ) def test_is_sorted( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, input_data: list[int], descending: bool, # noqa: FBT001 expected: bool, # noqa: FBT001 ) -> None: - series = nw.from_native(nw_eager_constructor({"a": input_data}), eager_only=True)["a"] + series = nw.from_native(constructor_eager({"a": input_data}), eager_only=True)["a"] result = series.is_sorted(descending=descending) assert_equal_data({"a": [result]}, {"a": [expected]}) -def test_is_sorted_invalid(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor({"a": data_sorted}), eager_only=True)[ - "a" - ] +def test_is_sorted_invalid(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager({"a": data_sorted}), eager_only=True)["a"] with pytest.raises(TypeError): series.is_sorted(descending="invalid_type") # type: ignore[arg-type] diff --git a/tests/series_only/item_test.py b/tests/series_only/item_test.py index d467563702..521ce5af55 100644 --- a/tests/series_only/item_test.py +++ b/tests/series_only/item_test.py @@ -11,8 +11,8 @@ @pytest.mark.parametrize(("index", "expected"), [(0, 1), (1, 3)]) -def test_item(nw_eager_constructor: ConstructorEager, index: int, expected: int) -> None: - series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] +def test_item(constructor_eager: ConstructorEager, index: int, expected: int) -> None: + series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] result = series.item(index) assert_equal_data({"a": [result]}, {"a": [expected]}) assert_equal_data({"a": [series.head(1).item()]}, {"a": [1]}) @@ -24,7 +24,7 @@ def test_item(nw_eager_constructor: ConstructorEager, index: int, expected: int) series.item(None) -def test_out_of_range(nw_eager_constructor: ConstructorEager) -> None: - series = nw.from_native(nw_eager_constructor({"a": [1, 2]}), eager_only=True)["a"] +def test_out_of_range(constructor_eager: ConstructorEager) -> None: + series = nw.from_native(constructor_eager({"a": [1, 2]}), eager_only=True)["a"] with pytest.raises(IndexError, match="out of range"): series.item(2) diff --git a/tests/series_only/scatter_test.py b/tests/series_only/scatter_test.py index afa703dacd..d608f78f1a 100644 --- a/tests/series_only/scatter_test.py +++ b/tests/series_only/scatter_test.py @@ -39,9 +39,9 @@ def test_scatter( indices: int | Collection[int], values: int | Collection[int], expected: list[Any], - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, ) -> None: - constructor = partial(series, nw_eager_constructor) + constructor = partial(series, constructor_eager) s = constructor("s", data) df = s.to_frame().with_row_index("dont change me") unchanged_indexed = df.to_dict(as_series=False) @@ -63,8 +63,8 @@ def test_scatter_pandas_index() -> None: pd.testing.assert_series_equal(result.to_native(), expected) -def test_scatter_2862(nw_eager_constructor: ConstructorEager) -> None: - s = series(nw_eager_constructor, "a", [1, 2, 3]) +def test_scatter_2862(constructor_eager: ConstructorEager) -> None: + s = series(constructor_eager, "a", [1, 2, 3]) assert_equal_series(s.scatter(1, 999), [1, 999, 3], "a") assert_equal_series(s.scatter([0, 2], [999, 888]), [999, 2, 888], "a") assert_equal_series(s.scatter([2, 0], [999, 888]), [888, 2, 999], "a") diff --git a/tests/series_only/shape_test.py b/tests/series_only/shape_test.py index 3863671bf6..8f8ba638e5 100644 --- a/tests/series_only/shape_test.py +++ b/tests/series_only/shape_test.py @@ -8,9 +8,7 @@ from tests.utils import ConstructorEager -def test_shape(nw_eager_constructor: ConstructorEager) -> None: - result = nw.from_native(nw_eager_constructor({"a": [1, 2]}), eager_only=True)[ - "a" - ].shape +def test_shape(constructor_eager: ConstructorEager) -> None: + result = nw.from_native(constructor_eager({"a": [1, 2]}), eager_only=True)["a"].shape expected = (2,) assert result == expected diff --git a/tests/series_only/sort_test.py b/tests/series_only/sort_test.py index a6f2d9c181..8b74c6623b 100644 --- a/tests/series_only/sort_test.py +++ b/tests/series_only/sort_test.py @@ -21,14 +21,11 @@ ], ) def test_sort_series( - nw_eager_constructor: ConstructorEager, - descending: Any, - nulls_last: Any, - expected: Any, + constructor_eager: ConstructorEager, descending: Any, nulls_last: Any, expected: Any ) -> None: - series = nw.from_native( - nw_eager_constructor({"a": [1, 3, 2, None]}), eager_only=True - )["a"] + series = nw.from_native(constructor_eager({"a": [1, 3, 2, None]}), eager_only=True)[ + "a" + ] result = series.sort(descending=descending, nulls_last=nulls_last) assert_equal_data({"a": result}, {"a": expected}) diff --git a/tests/series_only/tail_test.py b/tests/series_only/tail_test.py index 8e1de08e44..43f9866094 100644 --- a/tests/series_only/tail_test.py +++ b/tests/series_only/tail_test.py @@ -7,8 +7,8 @@ @pytest.mark.parametrize("n", [2, -1]) -def test_tail_series(nw_eager_constructor: ConstructorEager, n: int) -> None: - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True) +def test_tail_series(constructor_eager: ConstructorEager, n: int) -> None: + df = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True) result = df.select(df["a"].tail(n)) expected = {"a": [2, 3]} assert_equal_data(result, expected) diff --git a/tests/series_only/to_arrow_test.py b/tests/series_only/to_arrow_test.py index 64eb345b88..6675ea2e31 100644 --- a/tests/series_only/to_arrow_test.py +++ b/tests/series_only/to_arrow_test.py @@ -14,9 +14,9 @@ from tests.utils import ConstructorEager -def test_to_arrow(nw_eager_constructor: ConstructorEager) -> None: +def test_to_arrow(constructor_eager: ConstructorEager) -> None: data = [1, 2, 3] - result = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ + result = nw.from_native(constructor_eager({"a": data}), eager_only=True)[ "a" ].to_arrow() @@ -25,16 +25,16 @@ def test_to_arrow(nw_eager_constructor: ConstructorEager) -> None: def test_to_arrow_with_nulls( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pandas_constructor" in str(nw_eager_constructor) or "modin_constructor" in str( - nw_eager_constructor + if "pandas_constructor" in str(constructor_eager) or "modin_constructor" in str( + constructor_eager ): request.applymarker(pytest.mark.xfail) data = [1, 2, None] result = ( - nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] .cast(nw.Int64) .to_arrow() ) diff --git a/tests/series_only/to_dummy_test.py b/tests/series_only/to_dummy_test.py index d3d04cdbda..df301a6978 100644 --- a/tests/series_only/to_dummy_test.py +++ b/tests/series_only/to_dummy_test.py @@ -10,8 +10,8 @@ @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies(nw_eager_constructor: ConstructorEager, sep: str) -> None: - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].alias("a") +def test_to_dummies(constructor_eager: ConstructorEager, sep: str) -> None: + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias("a") result = s.to_dummies(separator=sep) expected = {f"a{sep}x": [1, 0, 0], f"a{sep}y": [0, 1, 0], f"a{sep}z": [0, 0, 1]} @@ -19,8 +19,8 @@ def test_to_dummies(nw_eager_constructor: ConstructorEager, sep: str) -> None: @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_drop_first(nw_eager_constructor: ConstructorEager, sep: str) -> None: - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].alias("a") +def test_to_dummies_drop_first(constructor_eager: ConstructorEager, sep: str) -> None: + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias("a") result = s.to_dummies(drop_first=True, separator=sep) expected = {f"a{sep}y": [0, 1, 0], f"a{sep}z": [0, 0, 1]} @@ -28,12 +28,10 @@ def test_to_dummies_drop_first(nw_eager_constructor: ConstructorEager, sep: str) @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_with_nulls(nw_eager_constructor: ConstructorEager, sep: str) -> None: - if "pandas_nullable_constructor" not in str(nw_eager_constructor): +def test_to_dummies_with_nulls(constructor_eager: ConstructorEager, sep: str) -> None: + if "pandas_nullable_constructor" not in str(constructor_eager): pytest.skip() - s = nw.from_native(nw_eager_constructor({"a": data_na}), eager_only=True)["a"].alias( - "a" - ) + s = nw.from_native(constructor_eager({"a": data_na}), eager_only=True)["a"].alias("a") result = s.to_dummies(separator=sep) expected = {f"a{sep}null": [0, 0, 1], f"a{sep}x": [1, 0, 0], f"a{sep}y": [0, 1, 0]} @@ -41,12 +39,8 @@ def test_to_dummies_with_nulls(nw_eager_constructor: ConstructorEager, sep: str) @pytest.mark.parametrize("sep", ["_", "-"]) -def test_to_dummies_drop_first_na( - nw_eager_constructor: ConstructorEager, sep: str -) -> None: - s = nw.from_native(nw_eager_constructor({"a": data_na}), eager_only=True)["a"].alias( - "a" - ) +def test_to_dummies_drop_first_na(constructor_eager: ConstructorEager, sep: str) -> None: + s = nw.from_native(constructor_eager({"a": data_na}), eager_only=True)["a"].alias("a") result = s.to_dummies(drop_first=True, separator=sep) expected = {f"a{sep}null": [0, 0, 1], f"a{sep}y": [0, 1, 0]} diff --git a/tests/series_only/to_frame_test.py b/tests/series_only/to_frame_test.py index 1310d69668..8f56f7f6fa 100644 --- a/tests/series_only/to_frame_test.py +++ b/tests/series_only/to_frame_test.py @@ -6,9 +6,9 @@ data = [1, 2, 3] -def test_to_frame(nw_eager_constructor: ConstructorEager) -> None: +def test_to_frame(constructor_eager: ConstructorEager) -> None: df = ( - nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] .alias("") .to_frame() ) diff --git a/tests/series_only/to_list_test.py b/tests/series_only/to_list_test.py index c573f3087f..e532f54799 100644 --- a/tests/series_only/to_list_test.py +++ b/tests/series_only/to_list_test.py @@ -6,6 +6,6 @@ data = [1, 2, 3] -def test_to_list(nw_eager_constructor: ConstructorEager) -> None: - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] +def test_to_list(constructor_eager: ConstructorEager) -> None: + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] assert_equal_data({"a": s.to_list()}, {"a": [1, 2, 3]}) diff --git a/tests/series_only/to_native_test.py b/tests/series_only/to_native_test.py index b5fc3c13ff..350d81764d 100644 --- a/tests/series_only/to_native_test.py +++ b/tests/series_only/to_native_test.py @@ -10,8 +10,8 @@ data = [4, 4, 4, 1, 6, 6, 4, 4, 1, 1] -def test_to_native(nw_eager_constructor: ConstructorEager) -> None: - orig_series = nw_eager_constructor({"a": data})["a"] # type: ignore[index] - nw_series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] +def test_to_native(constructor_eager: ConstructorEager) -> None: + orig_series = constructor_eager({"a": data})["a"] # type: ignore[index] + nw_series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] result = nw_series.to_native() assert isinstance(result, orig_series.__class__) diff --git a/tests/series_only/to_numpy_test.py b/tests/series_only/to_numpy_test.py index 10dbfc7e0d..21873760cb 100644 --- a/tests/series_only/to_numpy_test.py +++ b/tests/series_only/to_numpy_test.py @@ -17,15 +17,15 @@ def test_to_numpy( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "pandas_constructor" in str(nw_eager_constructor) or "modin_constructor" in str( - nw_eager_constructor + if "pandas_constructor" in str(constructor_eager) or "modin_constructor" in str( + constructor_eager ): request.applymarker(pytest.mark.xfail) data = [1, 2, None] - s = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"].cast( + s = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].cast( nw.Int64 ) assert s.to_numpy().dtype == "float64" @@ -35,17 +35,17 @@ def test_to_numpy( def test_to_numpy_tz_aware( - nw_eager_constructor: ConstructorEager, request: pytest.FixtureRequest + constructor_eager: ConstructorEager, request: pytest.FixtureRequest ) -> None: if ( - ("pandas_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) - or ("modin_pyarrow" in str(nw_eager_constructor) and PANDAS_VERSION < (2, 2)) - or ("pyarrow" in str(nw_eager_constructor) and is_windows()) + ("pandas_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) + or ("modin_pyarrow" in str(constructor_eager) and PANDAS_VERSION < (2, 2)) + or ("pyarrow" in str(constructor_eager) and is_windows()) ): request.applymarker(pytest.mark.xfail) request.applymarker(pytest.mark.xfail) df = nw.from_native( - nw_eager_constructor({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), + constructor_eager({"a": [datetime(2020, 1, 1), datetime(2020, 1, 2)]}), eager_only=True, ) df = df.select(nw.col("a").dt.replace_time_zone("Asia/Kathmandu")) diff --git a/tests/series_only/to_pandas_test.py b/tests/series_only/to_pandas_test.py index 8c0c0d5773..95cd969f14 100644 --- a/tests/series_only/to_pandas_test.py +++ b/tests/series_only/to_pandas_test.py @@ -19,19 +19,19 @@ @pytest.mark.skipif(PANDAS_VERSION < (2, 0, 0), reason="too old for pyarrow") def test_convert( - request: pytest.FixtureRequest, nw_eager_constructor: ConstructorEager + request: pytest.FixtureRequest, constructor_eager: ConstructorEager ) -> None: pytest.importorskip("pyarrow") if any( - cname in str(nw_eager_constructor) + cname in str(constructor_eager) for cname in ("pandas_nullable", "pandas_pyarrow", "modin_pyarrow") ): request.applymarker(pytest.mark.xfail) - series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ + series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias( "a" - ].alias("a") + ) result = series.to_pandas() assert_series_equal(result, pd.Series([1, 3, 2], name="a")) diff --git a/tests/series_only/to_polars_test.py b/tests/series_only/to_polars_test.py index 119d24300a..c99d6e889e 100644 --- a/tests/series_only/to_polars_test.py +++ b/tests/series_only/to_polars_test.py @@ -15,12 +15,12 @@ data = [1, 3, 2] -def test_series_to_polars(nw_eager_constructor: ConstructorEager) -> None: +def test_series_to_polars(constructor_eager: ConstructorEager) -> None: pytest.importorskip("pyarrow") from polars.testing import assert_series_equal result = ( - nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)["a"] + nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"] .alias("a") .to_polars() ) diff --git a/tests/series_only/value_counts_test.py b/tests/series_only/value_counts_test.py index 4e730f1d28..77a7656cf2 100644 --- a/tests/series_only/value_counts_test.py +++ b/tests/series_only/value_counts_test.py @@ -14,11 +14,11 @@ @pytest.mark.parametrize("name", [None, "count_name"]) def test_value_counts( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, normalize: Any, name: str | None, ) -> None: - if "pandas_nullable_constructor" in str(nw_eager_constructor) and PANDAS_VERSION < ( + if "pandas_nullable_constructor" in str(constructor_eager) and PANDAS_VERSION < ( 2, 2, ): @@ -34,9 +34,9 @@ def test_value_counts( expected_name = name or ("proportion" if normalize else "count") expected = {"a": expected_index, expected_name: expected_count} - series = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True)[ + series = nw.from_native(constructor_eager({"a": data}), eager_only=True)["a"].alias( "a" - ].alias("a") + ) sorted_result = series.value_counts(sort=True, name=name, normalize=normalize) assert_equal_data(sorted_result, expected) diff --git a/tests/series_only/zip_with_test.py b/tests/series_only/zip_with_test.py index f0f7e40331..b40ac19fd6 100644 --- a/tests/series_only/zip_with_test.py +++ b/tests/series_only/zip_with_test.py @@ -4,22 +4,22 @@ from tests.utils import ConstructorEager, assert_equal_data -def test_zip_with(nw_eager_constructor: ConstructorEager) -> None: - series1 = nw.from_native(nw_eager_constructor({"a": [1, 3, 2]}), eager_only=True)["a"] - series2 = nw.from_native(nw_eager_constructor({"a": [4, 4, 6]}), eager_only=True)["a"] - mask = nw.from_native( - nw_eager_constructor({"a": [True, False, True]}), eager_only=True - )["a"] +def test_zip_with(constructor_eager: ConstructorEager) -> None: + series1 = nw.from_native(constructor_eager({"a": [1, 3, 2]}), eager_only=True)["a"] + series2 = nw.from_native(constructor_eager({"a": [4, 4, 6]}), eager_only=True)["a"] + mask = nw.from_native(constructor_eager({"a": [True, False, True]}), eager_only=True)[ + "a" + ] result = series1.zip_with(mask, series2) expected = [1, 4, 2] assert_equal_data({"a": result}, {"a": expected}) -def test_zip_with_length_1(nw_eager_constructor: ConstructorEager) -> None: - series1 = nw.from_native(nw_eager_constructor({"a": [1]}), eager_only=True)["a"] - series2 = nw.from_native(nw_eager_constructor({"a": [4]}), eager_only=True)["a"] - mask = nw.from_native(nw_eager_constructor({"a": [False]}), eager_only=True)["a"] +def test_zip_with_length_1(constructor_eager: ConstructorEager) -> None: + series1 = nw.from_native(constructor_eager({"a": [1]}), eager_only=True)["a"] + series2 = nw.from_native(constructor_eager({"a": [4]}), eager_only=True)["a"] + mask = nw.from_native(constructor_eager({"a": [False]}), eager_only=True)["a"] result = series1.zip_with(mask, series2) expected = [4] diff --git a/tests/testing/assert_frame_equal_test.py b/tests/testing/assert_frame_equal_test.py index 4f7fc4c023..9b0f813b2f 100644 --- a/tests/testing/assert_frame_equal_test.py +++ b/tests/testing/assert_frame_equal_test.py @@ -22,9 +22,9 @@ def _assertion_error(detail: str) -> pytest.RaisesExc: return pytest.raises(AssertionError, match=re.escape(msg)) -def test_check_narwhals_objects(nw_frame_constructor: Constructor) -> None: +def test_check_narwhals_objects(constructor: Constructor) -> None: """Test that a type error is raised if the input is not a Narwhals object.""" - frame = nw_frame_constructor({"a": [1, 2, 3]}) + frame = constructor({"a": [1, 2, 3]}) msg = re.escape( "Expected `narwhals.DataFrame` or `narwhals.LazyFrame` instance, found" ) @@ -46,13 +46,13 @@ def test_implementation_mismatch() -> None: ) -def test_check_same_input_type(nw_eager_constructor: ConstructorEager) -> None: +def test_check_same_input_type(constructor_eager: ConstructorEager) -> None: """Test that left and right frames are either both eager or both lazy. - NOTE: Use `nw_eager_constructor` instead of `constructor` so that the roundtrip + NOTE: Use `constructor_eager` instead of `constructor` so that the roundtrip `.lazy().collect()` preserves the same implementation (and we raise the check after) """ - frame = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) + frame = nw.from_native(constructor_eager({"a": [1, 2, 3]})) msg = re.escape("inputs are different (unexpected input types)") with pytest.raises(AssertionError, match=msg): @@ -148,7 +148,7 @@ def test_check_same_input_type(nw_eager_constructor: ConstructorEager) -> None: ], ) def test_check_schema_mismatch( - nw_frame_constructor: Constructor, + constructor: Constructor, left_schema: IntoSchema, right_schema: IntoSchema, *, @@ -157,10 +157,10 @@ def test_check_schema_mismatch( context: AbstractContextManager[Any], ) -> None: data = {"a": [1, 2, 3], "b": [4.5, 6.7, 8.9], "z": ["foo", "bar", "baz"]} - left = nw.from_native(nw_frame_constructor(data)).select( + left = nw.from_native(constructor(data)).select( nw.col(name).cast(dtype) for name, dtype in left_schema.items() ) - right = nw.from_native(nw_frame_constructor(data)).select( + right = nw.from_native(constructor(data)).select( nw.col(name).cast(dtype) for name, dtype in right_schema.items() ) @@ -170,9 +170,9 @@ def test_check_schema_mismatch( ) -def test_height_mismatch(nw_frame_constructor: Constructor) -> None: - left = nw.from_native(nw_frame_constructor({"a": [1, 2, 3]})) - right = nw.from_native(nw_frame_constructor({"a": [1, 3]})) +def test_height_mismatch(constructor: Constructor) -> None: + left = nw.from_native(constructor({"a": [1, 2, 3]})) + right = nw.from_native(constructor({"a": [1, 3]})) with _assertion_error("height (row count) mismatch"): assert_frame_equal(left, right) @@ -180,18 +180,15 @@ def test_height_mismatch(nw_frame_constructor: Constructor) -> None: @pytest.mark.parametrize("check_row_order", [True, False]) def test_check_row_order( - nw_frame_constructor: Constructor, - request: pytest.FixtureRequest, - *, - check_row_order: bool, + constructor: Constructor, request: pytest.FixtureRequest, *, check_row_order: bool ) -> None: - if "pandas" in str(nw_frame_constructor): # pragma: no cover + if "pandas" in str(constructor): # pragma: no cover if PANDAS_VERSION < (2, 2): reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "Unsupported List type" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -199,14 +196,10 @@ def test_check_row_order( b_expr = nw.col("b").cast(nw.List(nw.String())) left = ( - nw.from_native(nw_frame_constructor(data)) - .with_columns(b_expr) - .sort("a", descending=False) + nw.from_native(constructor(data)).with_columns(b_expr).sort("a", descending=False) ) right = ( - nw.from_native(nw_frame_constructor(data)) - .with_columns(b_expr) - .sort("a", descending=True) + nw.from_native(constructor(data)).with_columns(b_expr).sort("a", descending=True) ) context = ( @@ -220,44 +213,41 @@ def test_check_row_order( def test_check_row_order_nested_only( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest + constructor: Constructor, request: pytest.FixtureRequest ) -> None: - if "pandas" in str(nw_frame_constructor): # pragma: no cover + if "pandas" in str(constructor): # pragma: no cover if PANDAS_VERSION < (2, 2): reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "dask" in str(nw_frame_constructor): + if "dask" in str(constructor): reason = "Unsupported List type" request.applymarker(pytest.mark.xfail(reason=reason)) data = {"b": [["x", "y"], ["x", "z"]]} b_expr = nw.col("b").cast(nw.List(nw.String())) - left = nw.from_native(nw_frame_constructor(data)).select(b_expr) + left = nw.from_native(constructor(data)).select(b_expr) msg = "`check_row_order=False` is not supported (yet) with only nested data type." with pytest.raises(NotImplementedError, match=re.escape(msg)): assert_frame_equal(left, left, check_row_order=False) -def test_self_equal(nw_frame_constructor: Constructor, testing_data: Data) -> None: +def test_self_equal(constructor: Constructor, testing_data: Data) -> None: """Test that a dataframe is equal to itself, including nested dtypes with nulls. We are dropping columns which type is unsupported by _some_ backend. """ cols_to_drop = ("categorical", "enum", "duration", "struct", "time") - if "pandas" in str(nw_frame_constructor) and PANDAS_VERSION < ( - 2, - 2, - ): # pragma: no cover + if "pandas" in str(constructor) and PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) _data = {k: v for k, v in testing_data.items() if k not in cols_to_drop} - df = nw.from_native(nw_frame_constructor(_data)) + df = nw.from_native(constructor(_data)) assert_frame_equal(df, df) # Keep to cover early return when no rows present but same schema diff --git a/tests/testing/assert_series_equal_test.py b/tests/testing/assert_series_equal_test.py index 0ee028917e..c4826c695e 100644 --- a/tests/testing/assert_series_equal_test.py +++ b/tests/testing/assert_series_equal_test.py @@ -32,21 +32,21 @@ def series_from_native(native: IntoSeriesT) -> nw.Series[IntoSeriesT]: def test_self_equal( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, testing_data: Data, testing_schema: IntoSchema, ) -> None: """Test that a series is equal to itself, including nested dtypes with nulls.""" - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): # TODO(FBruzzesi): Investigate which conversion is failing aside from nested dtypes request.applymarker(pytest.mark.xfail) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 15, 0, ): # pragma: no cover @@ -56,7 +56,7 @@ def test_self_equal( ) pytest.skip(reason=reason) - if "pyarrow_table" in str(nw_eager_constructor): + if "pyarrow_table" in str(constructor_eager): # Replace Enum with Categorical, since Pyarrow does not support Enum data = dict(testing_data) schema = {**testing_schema, "enum": nw.Categorical()} @@ -64,7 +64,7 @@ def test_self_equal( data = dict(testing_data) schema = dict(testing_schema) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) for name, dtype in schema.items(): assert_series_equal(df[name].cast(dtype), df[name].cast(dtype)) @@ -93,10 +93,10 @@ def test_implementation_mismatch() -> None: ], ) def test_metadata_checks( - nw_eager_constructor: ConstructorEager, setup_fn: SetupFn, error_msg: str + constructor_eager: ConstructorEager, setup_fn: SetupFn, error_msg: str ) -> None: """Test metadata validation (length, dtype, name).""" - series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] left, right = setup_fn(series) with _assertion_error(error_msg): @@ -112,7 +112,7 @@ def test_metadata_checks( ], ) def test_metadata_checks_with_flags( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, setup_fn: SetupFn, error_msg: str, *, @@ -120,7 +120,7 @@ def test_metadata_checks_with_flags( check_names: bool, ) -> None: """Test the effect of check_dtypes and check_names flags.""" - series = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]}), eager_only=True)["a"] + series = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] left, right = setup_fn(series) with _assertion_error(error_msg): @@ -142,25 +142,25 @@ def test_metadata_checks_with_flags( ) def test_check_order( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, dtype: nw.dtypes.DType, *, check_order: bool, context: AbstractContextManager[Any], ) -> None: """Test check_order behavior with nested and simple data.""" - if "cudf" in str(nw_eager_constructor) and dtype.is_nested(): + if "cudf" in str(constructor_eager) and dtype.is_nested(): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2) and dtype.is_nested(): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") data: list[Any] = [[1, 2, 3]] if dtype.is_nested() else [1, 2, 3] - frame = nw.from_native(nw_eager_constructor({"a": data}), eager_only=True) + frame = nw.from_native(constructor_eager({"a": data}), eager_only=True) left = right = frame["a"].cast(dtype) with context: @@ -174,9 +174,9 @@ def test_check_order( {"left": ["x", None, None], "right": [None, "x", "y"]}, # Different null counts ], ) -def test_null_mismatch(nw_eager_constructor: ConstructorEager, null_data: Data) -> None: +def test_null_mismatch(constructor_eager: ConstructorEager, null_data: Data) -> None: """Test null value mismatch detection.""" - frame = nw.from_native(nw_eager_constructor(null_data), eager_only=True) + frame = nw.from_native(constructor_eager(null_data), eager_only=True) left, right = frame["left"], frame["right"] with _assertion_error("null value mismatch"): assert_series_equal(left, right, check_names=False) @@ -191,7 +191,7 @@ def test_null_mismatch(nw_eager_constructor: ConstructorEager, null_data: Data) ], ) def test_numeric( - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, *, check_exact: bool, abs_tol: float, @@ -203,7 +203,7 @@ def test_numeric( "right": [1.01, float("nan"), float("inf"), None, 1.11], } - frame = nw.from_native(nw_eager_constructor(data), eager_only=True) + frame = nw.from_native(constructor_eager(data), eager_only=True) left, right = frame["left"], frame["right"] with context: assert_series_equal( @@ -259,7 +259,7 @@ def test_numeric( ) def test_list_like( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, l_vals: list[list[Any]], r_vals: list[list[Any]], *, @@ -267,18 +267,18 @@ def test_list_like( context: AbstractContextManager[Any], dtype: nw.dtypes.DType, ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) pytest.importorskip("pyarrow") if ( - "pyarrow_table" in str(nw_eager_constructor) + "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < (14, 0) and dtype == nw.Array ): # pragma: no cover @@ -289,7 +289,7 @@ def test_list_like( pytest.skip(reason=reason) data = {"left": l_vals, "right": r_vals} - frame = nw.from_native(nw_eager_constructor(data), eager_only=True) + frame = nw.from_native(constructor_eager(data), eager_only=True) left, right = frame["left"].cast(dtype), frame["right"].cast(dtype) with context: assert_series_equal(left, right, check_names=False, check_exact=check_exact) @@ -320,18 +320,18 @@ def test_list_like( ) def test_struct( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, l_vals: list[dict[str, Any]], r_vals: list[dict[str, Any]], *, check_exact: bool, context: AbstractContextManager[Any], ) -> None: - if "cudf" in str(nw_eager_constructor): + if "cudf" in str(constructor_eager): reason = "NotImplementedError" request.applymarker(pytest.mark.xfail(reason=reason)) - if "pandas" in str(nw_eager_constructor): + if "pandas" in str(constructor_eager): if PANDAS_VERSION < (2, 2): # pragma: no cover reason = "Pandas too old for nested dtypes" pytest.skip(reason=reason) @@ -339,7 +339,7 @@ def test_struct( dtype = nw.Struct({"a": nw.Float32(), "b": nw.List(nw.String())}) data = {"left": l_vals, "right": r_vals} - frame = nw.from_native(nw_eager_constructor(data), eager_only=True) + frame = nw.from_native(constructor_eager(data), eager_only=True) left, right = frame["left"].cast(dtype), frame["right"].cast(dtype) with context: assert_series_equal(left, right, check_names=False, check_exact=check_exact) @@ -374,13 +374,13 @@ def test_non_nw_series() -> None: ) def test_categorical_as_str( request: pytest.FixtureRequest, - nw_eager_constructor: ConstructorEager, + constructor_eager: ConstructorEager, *, categorical_as_str: bool, context: AbstractContextManager[Any], ) -> None: if ( - "polars" in str(nw_eager_constructor) + "polars" in str(constructor_eager) and POLARS_VERSION >= (1, 32) and not categorical_as_str ): @@ -388,11 +388,11 @@ def test_categorical_as_str( # exists but it does nothing in python. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(nw_eager_constructor) and not categorical_as_str: + if "pyarrow_table" in str(constructor_eager) and not categorical_as_str: # pyarrow dictionary dtype compares values, not the encoding. request.applymarker(pytest.mark.xfail) - if "pyarrow_table" in str(nw_eager_constructor) and PYARROW_VERSION < ( + if "pyarrow_table" in str(constructor_eager) and PYARROW_VERSION < ( 15, 0, ): # pragma: no cover @@ -406,7 +406,7 @@ def test_categorical_as_str( "left": ["beluga", "dolphin", "narwhal", "orca"], "right": ["unicorn", "orca", "narwhal", "orca"], } - frame = nw.from_native(nw_eager_constructor(data), eager_only=True) + frame = nw.from_native(constructor_eager(data), eager_only=True) left = frame["left"].cast(nw.Categorical())[2:] right = frame["right"].cast(nw.Categorical())[2:] diff --git a/tests/testing/plugin_test.py b/tests/testing/plugin_test.py index 622ef6a19c..8f3d74e1df 100644 --- a/tests/testing/plugin_test.py +++ b/tests/testing/plugin_test.py @@ -5,7 +5,7 @@ pytest_plugins = ["pytester"] -def test_nw_eager_constructor_fixture_runs_for_each_backend( +def test_constructor_eager_fixture_runs_for_each_backend( pytester: pytest.Pytester, ) -> None: pytest.importorskip("pandas") diff --git a/tests/translate/from_native_test.py b/tests/translate/from_native_test.py index 5fcd2076ff..a0d94b99fb 100644 --- a/tests/translate/from_native_test.py +++ b/tests/translate/from_native_test.py @@ -507,13 +507,8 @@ def test_from_native_roundtrip_identity(native: Any, kwds: dict[str, Any]) -> No assert roundtrip is native -def test_pyspark_connect_deps_2517( - nw_frame_constructor: Constructor, -) -> None: # pragma: no cover - if not ( - "pyspark" in str(nw_frame_constructor) - and "sqlframe" not in str(nw_frame_constructor) - ): +def test_pyspark_connect_deps_2517(constructor: Constructor) -> None: # pragma: no cover + if not ("pyspark" in str(constructor) and "sqlframe" not in str(constructor)): # Only run this slow test if `--constructors=pyspark` is passed return pytest.importorskip("pyspark") @@ -529,13 +524,11 @@ def test_pyspark_connect_deps_2517( nw.from_native(spark.createDataFrame([(1,)], ["a"])) -def test_eager_only_pass_through_main(nw_frame_constructor: Constructor) -> None: - if not any( - s in str(nw_frame_constructor) for s in ("pyspark", "dask", "ibis", "duckdb") - ): +def test_eager_only_pass_through_main(constructor: Constructor) -> None: + if not any(s in str(constructor) for s in ("pyspark", "dask", "ibis", "duckdb")): pytest.skip(reason="Non lazy or polars") - df = nw_frame_constructor(data) + df = constructor(data) r1 = nw.from_native(df, eager_only=False, pass_through=False) r2 = nw.from_native(df, eager_only=False, pass_through=True) diff --git a/tests/translate/get_native_namespace_test.py b/tests/translate/get_native_namespace_test.py index 0443d86594..5a15069ed2 100644 --- a/tests/translate/get_native_namespace_test.py +++ b/tests/translate/get_native_namespace_test.py @@ -62,25 +62,25 @@ def _get_expected_namespace(constructor_name: str) -> Any | None: # noqa: PLR09 return None # pragma: no cover -def test_native_namespace_frame(nw_frame_constructor: Constructor) -> None: - constructor_name = str(nw_frame_constructor) +def test_native_namespace_frame(constructor: Constructor) -> None: + constructor_name = str(constructor) if "pyspark" in constructor_name and "sqlframe" not in constructor_name: pytest.skip(reason="Requires special handling for spark local vs spark connect") expected_namespace = _get_expected_namespace(constructor_name=constructor_name) - df = nw.from_native(nw_frame_constructor(data)) + df = nw.from_native(constructor(data)) assert nw.get_native_namespace(df) is expected_namespace assert nw.get_native_namespace(df.to_native()) is expected_namespace assert nw.get_native_namespace(df.lazy().to_native()) is expected_namespace -def test_native_namespace_series(nw_eager_constructor: ConstructorEager) -> None: - constructor_name = str(nw_eager_constructor) +def test_native_namespace_series(constructor_eager: ConstructorEager) -> None: + constructor_name = str(constructor_eager) expected_namespace = _get_expected_namespace(constructor_name=constructor_name) - df = nw.from_native(nw_eager_constructor(data), eager_only=True) + df = nw.from_native(constructor_eager(data), eager_only=True) assert nw.get_native_namespace(df["a"].to_native()) is expected_namespace assert nw.get_native_namespace(df, df["a"].to_native()) is expected_namespace diff --git a/tests/translate/to_native_test.py b/tests/translate/to_native_test.py index 1ea9d7014c..f84cf80dd6 100644 --- a/tests/translate/to_native_test.py +++ b/tests/translate/to_native_test.py @@ -25,15 +25,11 @@ ], ) def test_to_native( - nw_eager_constructor: ConstructorEager, - method: str, - *, - pass_through: bool, - context: Any, + constructor_eager: ConstructorEager, method: str, *, pass_through: bool, context: Any ) -> None: if method == "to_numpy": pytest.importorskip("numpy") - df = nw.from_native(nw_eager_constructor({"a": [1, 2, 3]})) + df = nw.from_native(constructor_eager({"a": [1, 2, 3]})) with context: nw.to_native(getattr(df, method)(), pass_through=pass_through) diff --git a/tests/utils.py b/tests/utils.py index a661aecbf7..c51ee91d00 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -61,7 +61,7 @@ def get_module_version_as_tuple(module_name: str) -> tuple[int, ...]: ) ID_CUDF = frozenset(("cudf",)) _CONSTRUCTOR_FIXTURE_NAMES = frozenset[str]( - ("nw_eager_constructor", "nw_frame_constructor", "nw_pandas_like_constructor") + ("constructor_eager", "constructor", "constructor_pandas_like") ) @@ -200,13 +200,9 @@ def windows_has_tzdata() -> bool: # pragma: no cover return (Path.home() / "Downloads" / "tzdata").exists() -def is_pyarrow_windows_no_tzdata(nw_frame_constructor: Constructor, /) -> bool: +def is_pyarrow_windows_no_tzdata(constructor: Constructor, /) -> bool: """Skip test on Windows when the tz database is not configured.""" - return ( - "pyarrow" in str(nw_frame_constructor) - and is_windows() - and not windows_has_tzdata() - ) + return "pyarrow" in str(constructor) and is_windows() and not windows_has_tzdata() def uses_pyarrow_backend(constructor: Constructor | ConstructorEager) -> bool: @@ -241,9 +237,9 @@ def time_unit_compat(time_unit: TimeUnit, request: pytest.FixtureRequest, /) -> return time_unit -def is_pyspark_connect(nw_frame_constructor: Constructor) -> bool: +def is_pyspark_connect(constructor: Constructor) -> bool: is_spark_connect = bool(os.environ.get("SPARK_CONNECT", None)) - return is_spark_connect and ("pyspark" in str(nw_frame_constructor)) + return is_spark_connect and ("pyspark" in str(constructor)) def xfail_if_pyspark_connect( # pragma: no cover diff --git a/tests/v1_test.py b/tests/v1_test.py index 9f8838b7f7..9882c4ed15 100644 --- a/tests/v1_test.py +++ b/tests/v1_test.py @@ -309,16 +309,16 @@ def test_enum_v1_is_enum_unstable() -> None: def test_cast_to_enum_v1( - request: pytest.FixtureRequest, nw_frame_constructor: Constructor + request: pytest.FixtureRequest, constructor: Constructor ) -> None: # Backends that do not (yet) support Enum dtype if any( - backend in str(nw_frame_constructor) + backend in str(constructor) for backend in ("pyarrow_table", "sqlframe", "pyspark", "ibis") ): request.applymarker(pytest.mark.xfail) - df_native = nw_frame_constructor({"a": ["a", "b"]}) + df_native = constructor({"a": ["a", "b"]}) msg = re.escape("Converting to Enum is not supported in narwhals.stable.v1") with pytest.raises(NotImplementedError, match=msg): @@ -454,17 +454,17 @@ def test_all_horizontal() -> None: assert_equal_data(result, expected) -def test_with_row_index(nw_frame_constructor: Constructor) -> None: - if "duckdb" in str(nw_frame_constructor) and DUCKDB_VERSION < (1, 3): +def test_with_row_index(constructor: Constructor) -> None: + if "duckdb" in str(constructor) and DUCKDB_VERSION < (1, 3): pytest.skip() data = {"abc": ["foo", "bars"], "xyz": [100, 200], "const": [42, 42]} - frame = nw_v1.from_native(nw_frame_constructor(data)) + frame = nw_v1.from_native(constructor(data)) msg = "Cannot pass `order_by`" context = ( pytest.raises(TypeError, match=msg) - if any(x in str(nw_frame_constructor) for x in ("duckdb", "pyspark")) + if any(x in str(constructor) for x in ("duckdb", "pyspark")) else does_not_raise() ) @@ -866,9 +866,9 @@ def func( func(pl.DataFrame(data), pd.Series(data["a"])) -def test_expr_sample(nw_eager_constructor: ConstructorEager) -> None: +def test_expr_sample(constructor_eager: ConstructorEager) -> None: df = nw_v1.from_native( - nw_eager_constructor({"a": [1, 2, 3], "b": [4, 5, 6]}), eager_only=True + constructor_eager({"a": [1, 2, 3], "b": [4, 5, 6]}), eager_only=True ) result_expr = df.select(nw_v1.col("a").sample(n=2)).shape @@ -886,19 +886,17 @@ def test_is_frame() -> None: assert nw_v1.dependencies.is_narwhals_dataframe(lf.collect()) -def test_with_version(nw_frame_constructor: Constructor) -> None: - lf = nw_v1.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() +def test_with_version(constructor: Constructor) -> None: + lf = nw_v1.from_native(constructor({"a": [1, 2]})).lazy() assert isinstance(lf, nw_v1.LazyFrame) assert lf._compliant_frame._with_version(Version.MAIN)._version is Version.MAIN @pytest.mark.parametrize("n", [1, 2]) @pytest.mark.parametrize("offset", [1, 2]) -def test_gather_every( - nw_eager_constructor: ConstructorEager, n: int, offset: int -) -> None: +def test_gather_every(constructor_eager: ConstructorEager, n: int, offset: int) -> None: data = {"a": list(range(10))} - df_v1 = nw_v1.from_native(nw_eager_constructor(data)) + df_v1 = nw_v1.from_native(constructor_eager(data)) result = df_v1.gather_every(n=n, offset=offset) expected = {"a": data["a"][offset::n]} assert_equal_data(result, expected) @@ -1156,26 +1154,26 @@ def test_series_from_iterable( assert_equal_series(result, expected, name) -def test_mode_single_expr(nw_eager_constructor: ConstructorEager) -> None: +def test_mode_single_expr(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - df = nw_v1.from_native(nw_eager_constructor(data)) + df = nw_v1.from_native(constructor_eager(data)) result = df.select(nw_v1.col("a").mode()).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series(nw_eager_constructor: ConstructorEager) -> None: +def test_mode_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - series = nw_v1.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw_v1.from_native(constructor_eager(data), eager_only=True)["a"] result = series.mode().sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_different_lengths(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw_v1.from_native(nw_eager_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw_v1.from_native(constructor_eager({"a": [1, 1, 2], "b": [4, 5, 6]})) with pytest.raises(ShapeError): df.select(nw_v1.col("a", "b").mode()) @@ -1188,10 +1186,8 @@ def test_dtype___slots__(dtype: DType) -> None: dtype.i_also_dont_exist = 528329 # type: ignore[attr-defined] -def test_any_value_expr( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "dask" in str(nw_frame_constructor): +def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "dask" in str(constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -1200,15 +1196,15 @@ def test_any_value_expr( "b": [1, 2, 3, 4, 5, 6], "c": [None, None, 1, None, 2, None], } - df = nw_v1.from_native(nw_frame_constructor(data)) + df = nw_v1.from_native(constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df.select(nw_v1.col("a", "b").any_value()) -def test_any_value_series(nw_eager_constructor: ConstructorEager) -> None: +def test_any_value_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 1, 2, 2, 3]} - df = nw_v1.from_native(nw_eager_constructor(data)) + df = nw_v1.from_native(constructor_eager(data)) with pytest.warns(NarwhalsUnstableWarning): df["a"].any_value() diff --git a/tests/v2_test.py b/tests/v2_test.py index e819eb4d04..7a1903425c 100644 --- a/tests/v2_test.py +++ b/tests/v2_test.py @@ -346,8 +346,8 @@ def fun2(self, df: Any) -> Any: # pragma: no cover Foo().func() -def test_with_version(nw_frame_constructor: Constructor) -> None: - lf = nw_v2.from_native(nw_frame_constructor({"a": [1, 2]})).lazy() +def test_with_version(constructor: Constructor) -> None: + lf = nw_v2.from_native(constructor({"a": [1, 2]})).lazy() assert isinstance(lf, nw_v2.LazyFrame) assert lf._compliant_frame._with_version(Version.MAIN)._version is Version.MAIN @@ -501,34 +501,32 @@ def test_series_from_iterable( assert_equal_series(result, expected, name) -def test_mode_single_expr(nw_eager_constructor: ConstructorEager) -> None: +def test_mode_single_expr(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - df = nw_v2.from_native(nw_eager_constructor(data)) + df = nw_v2.from_native(constructor_eager(data)) result = df.select(nw_v2.col("a").mode()).sort("a") expected = {"a": [1, 2]} assert_equal_data(result, expected) -def test_mode_series(nw_eager_constructor: ConstructorEager) -> None: +def test_mode_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 2, 2, 3], "b": [1, 2, 3, 3, 4]} - series = nw_v2.from_native(nw_eager_constructor(data), eager_only=True)["a"] + series = nw_v2.from_native(constructor_eager(data), eager_only=True)["a"] result = series.mode().sort() expected = {"a": [1, 2]} assert_equal_data({"a": result}, expected) -def test_mode_different_lengths(nw_eager_constructor: ConstructorEager) -> None: - if "polars" in str(nw_eager_constructor) and POLARS_VERSION < (1, 10): +def test_mode_different_lengths(constructor_eager: ConstructorEager) -> None: + if "polars" in str(constructor_eager) and POLARS_VERSION < (1, 10): pytest.skip() - df = nw_v2.from_native(nw_eager_constructor({"a": [1, 1, 2], "b": [4, 5, 6]})) + df = nw_v2.from_native(constructor_eager({"a": [1, 1, 2], "b": [4, 5, 6]})) with pytest.raises(ShapeError): df.select(nw_v2.col("a", "b").mode()) -def test_any_value_expr( - nw_frame_constructor: Constructor, request: pytest.FixtureRequest -) -> None: - if "dask" in str(nw_frame_constructor): +def test_any_value_expr(constructor: Constructor, request: pytest.FixtureRequest) -> None: + if "dask" in str(constructor): reason = "sample does not allow n, use frac instead" request.applymarker(pytest.mark.xfail(reason=reason)) @@ -537,15 +535,15 @@ def test_any_value_expr( "b": [1, 2, 3, 4, 5, 6], "c": [None, None, 1, None, 2, None], } - df = nw_v2.from_native(nw_frame_constructor(data)) + df = nw_v2.from_native(constructor(data)) with pytest.warns(NarwhalsUnstableWarning): df.select(nw_v2.col("a", "b").any_value()) -def test_any_value_series(nw_eager_constructor: ConstructorEager) -> None: +def test_any_value_series(constructor_eager: ConstructorEager) -> None: data = {"a": [1, 1, 1, 2, 2, 3]} - df = nw_v2.from_native(nw_eager_constructor(data)) + df = nw_v2.from_native(constructor_eager(data)) with pytest.warns(NarwhalsUnstableWarning): df["a"].any_value() From 86b58a1d3fcd1b41bb79c09772af9a23393634fc Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sun, 19 Apr 2026 10:28:07 +0200 Subject: [PATCH 07/11] use new fixture directly in hyp cases --- tests/expr_and_series/arithmetic_test.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/expr_and_series/arithmetic_test.py b/tests/expr_and_series/arithmetic_test.py index af0c464e5b..dd0f25bdfe 100644 --- a/tests/expr_and_series/arithmetic_test.py +++ b/tests/expr_and_series/arithmetic_test.py @@ -160,13 +160,15 @@ def test_truediv_same_dims( @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") @pytest.mark.slow -def test_floordiv(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(constructor_eager) for x in ["modin", "cudf"]): +def test_floordiv( + nw_eager_constructor: ConstructorEager, *, left: int, right: int +) -> None: + if any(x in str(nw_eager_constructor) for x in ["modin", "cudf"]): # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left // right]} - result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( nw.col("a") // right ) assert_equal_data(result, expected) @@ -175,14 +177,14 @@ def test_floordiv(constructor_eager: ConstructorEager, *, left: int, right: int) @pytest.mark.slow @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") -def test_mod(constructor_eager: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(constructor_eager) for x in ["pandas_pyarrow", "modin", "cudf"]): +def test_mod(nw_eager_constructor: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin", "cudf"]): # pandas[pyarrow] does not implement mod # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left % right]} - result = nw.from_native(constructor_eager({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( nw.col("a") % right ) assert_equal_data(result, expected) From 9980dd8a0fe6095a04561110f92aa15216d414ce Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Sun, 19 Apr 2026 11:31:19 +0200 Subject: [PATCH 08/11] Adjust documentation --- docs/api-reference/testing.md | 43 ++++++++++++++++++++--------------- narwhals/testing/typing.py | 2 +- tests/conftest.py | 10 ++++---- utils/sort_api_reference.py | 2 +- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/docs/api-reference/testing.md b/docs/api-reference/testing.md index 4a8109fe32..d4bf928e59 100644 --- a/docs/api-reference/testing.md +++ b/docs/api-reference/testing.md @@ -1,10 +1,12 @@ # `narwhals.testing` -## Asserts +## Assertions ::: narwhals.testing handler: python options: + show_root_heading: false + heading_level: 3 members: - assert_frame_equal - assert_series_equal @@ -18,19 +20,22 @@ to build native frames from a column-oriented python `dict`. | Fixture | Backends | |---|---| -| `constructor` | every selected backend (eager + lazy) | -| `constructor_eager` | only eager backends | +| `nw_frame_constructor` | every selected backend (eager + lazy) | +| `nw_eager_constructor` | only eager backends | +| `nw_pandas_like_constructor` | pandas-like backends | -The selection is controlled by two CLI options: +### Pytest options -* `--constructors=pandas,polars[lazy],duckdb`: comma-separated list. - Defaults to [`DEFAULT_CONSTRUCTORS`][narwhals.testing.constructors.DEFAULT_CONSTRUCTORS] +The backend selection is controlled by the following CLI options: + +* `--nw-backends=pandas,polars[lazy],duckdb`: comma-separated list. + Defaults to [`DEFAULT_BACKENDS`][narwhals.testing.constructors.DEFAULT_BACKENDS] intersected with the backends installed in the current environment. -* `--all-cpu-constructors`: shortcut for "every CPU backend that is installed". -* `--use-external-constructor`: Skip narwhals.testing's parametrisation and let +* `--nw-all-backends`: shortcut for "every **CPU** backend that is installed". +* `--use-nw-external-constructor`: Skip narwhals.testing's parametrisation and let another plugin provide the `constructor*` fixtures. -Set the `NARWHALS_DEFAULT_CONSTRUCTORS` environment variable to override the default +Set the `NARWHALS_DEFAULT_BACKENDS` environment variable to override the default list (useful e.g. when running under `cudf.pandas`). ### Quick start @@ -43,12 +48,12 @@ from typing import TYPE_CHECKING import narwhals as nw if TYPE_CHECKING: - from narwhals.testing.typing import ConstructorEager, Data + from narwhals.testing.typing import EagerFrameConstructor, Data -def test_shape(constructor_eager: ConstructorEager) -> None: +def test_shape(nw_eager_constructor: EagerFrameConstructor) -> None: data: Data = {"x": [1, 2, 3]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_eager_constructor(data), eager_only=True) assert df.shape == (3, 1) ``` @@ -56,17 +61,19 @@ The fixtures are parametrised against every supported backend that is installed in the current environment. Filter the matrix on the command line: ```bash -pytest --constructors="pandas,polars[lazy]" -pytest --all-cpu-constructors +pytest --nw-backends="pandas,polars[lazy]" +pytest --all-nw-backends ``` -### Type aliases +## Type aliases ::: narwhals.testing.typing handler: python options: + show_root_heading: false + heading_level: 3 members: - - Constructor - - ConstructorEager - - ConstructorLazy - Data + - FrameConstructor + - EagerFrameConstructor + - LazyFrameConstructor diff --git a/narwhals/testing/typing.py b/narwhals/testing/typing.py index 19aabb9e3b..43652830dc 100644 --- a/narwhals/testing/typing.py +++ b/narwhals/testing/typing.py @@ -16,4 +16,4 @@ Data: TypeAlias = dict[str, Any] # TODO(Unassined): This should have a better annotation -"""A column-oriented mapping used as input to a [`Constructor`][].""" +"""A column-oriented mapping used as input to a [`narwhals.testing.constructors.FrameConstructor`][].""" diff --git a/tests/conftest.py b/tests/conftest.py index ff79ea62f6..2f73aa78af 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -120,17 +120,17 @@ def nested_dtype(request: pytest.FixtureRequest) -> NestedOrEnumDType: return dtype +# The following fixtures are aliases of those registered in `narwhals/testing/pytest_plugin.py` +# in order to be backward compatible with the old fixture names and avoid having to change +# every single test. +# TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly @pytest.fixture def constructor(nw_frame_constructor: FrameConstructor) -> FrameConstructor: - # Alias fixture for backward compatibility - # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly return nw_frame_constructor @pytest.fixture def constructor_eager(nw_eager_constructor: EagerFrameConstructor) -> FrameConstructor: - # Alias fixture for backward compatibility - # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly return nw_eager_constructor @@ -138,6 +138,4 @@ def constructor_eager(nw_eager_constructor: EagerFrameConstructor) -> FrameConst def constructor_pandas_like( nw_pandas_like_constructor: EagerFrameConstructor, ) -> FrameConstructor: - # Alias fixture for backward compatibility - # TODO(FBruzzesi): Rm once all tests start using nw_frame_constructor directly return nw_pandas_like_constructor diff --git a/utils/sort_api_reference.py b/utils/sort_api_reference.py index 1b417ed63a..243ccbcd6d 100644 --- a/utils/sort_api_reference.py +++ b/utils/sort_api_reference.py @@ -42,7 +42,7 @@ def sort_list(match: re.Match[str]) -> str: PATH = Path("docs") / "api-reference" -FILES_TO_SKIP = {"dtypes", "typing"} +FILES_TO_SKIP = {"dtypes", "typing", "testing"} ret = max( sort_members_in_markdown(file_path=file_path) From 264ec9effd597aa78a95c8f554a313a3936e28c8 Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Tue, 21 Apr 2026 22:56:15 +0200 Subject: [PATCH 09/11] fix makefile --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4010bd8a74..7276495c95 100644 --- a/Makefile +++ b/Makefile @@ -47,6 +47,6 @@ test: ## Run unittest --editable .[ibis,modin,pyspark] \ --group core \ --group tests - $(VENV_BIN)/uv run --no-sync coverage run -m pytest tests --all-cpu-constructors --numprocesses=logical + $(VENV_BIN)/uv run --no-sync coverage run -m pytest tests --all-nw-backends --numprocesses=logical $(VENV_BIN)/uv run --no-sync coverage combine $(VENV_BIN)/uv run --no-sync coverage report --fail-under=95 From 005438e6ee83a17016487dd509d5ca9eb322df36 Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Tue, 21 Apr 2026 23:26:49 +0200 Subject: [PATCH 10/11] var name --- narwhals/testing/pytest_plugin.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/narwhals/testing/pytest_plugin.py b/narwhals/testing/pytest_plugin.py index 894a4f8d29..28e9701742 100644 --- a/narwhals/testing/pytest_plugin.py +++ b/narwhals/testing/pytest_plugin.py @@ -42,12 +42,12 @@ def _default_backend_ids() -> list[str]: """ if env := os.environ.get("NARWHALS_DEFAULT_BACKENDS"): # pragma: no cover return env.split(",") - from narwhals.testing.constructors import DEFAULT_CONSTRUCTORS, frame_constructor + from narwhals.testing.constructors import DEFAULT_BACKENDS, frame_constructor return [ name for name, constructor in frame_constructor._registry.items() - if constructor.is_available and name in DEFAULT_CONSTRUCTORS + if constructor.is_available and name in DEFAULT_BACKENDS ] From b0f91eea0599bcb472cfea3da2ea0bd809bbe9bc Mon Sep 17 00:00:00 2001 From: FBruzzesi Date: Tue, 21 Apr 2026 23:46:04 +0200 Subject: [PATCH 11/11] fixup arithmetic test --- tests/expr_and_series/arithmetic_test.py | 40 +++++++++++------------- 1 file changed, 19 insertions(+), 21 deletions(-) diff --git a/tests/expr_and_series/arithmetic_test.py b/tests/expr_and_series/arithmetic_test.py index dd0f25bdfe..ec6c2ff8bc 100644 --- a/tests/expr_and_series/arithmetic_test.py +++ b/tests/expr_and_series/arithmetic_test.py @@ -98,16 +98,16 @@ def test_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_dataframe: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_dataframe) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_dataframe(data), eager_only=True) result = df.select(getattr(df["a"], attr)(rhs)) assert_equal_data(result, {"a": expected}) @@ -128,29 +128,29 @@ def test_right_arithmetic_series( attr: str, rhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_dataframe: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__rmod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_dataframe) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1, 2, 3]} - df = nw.from_native(constructor_eager(data), eager_only=True) + df = nw.from_native(nw_dataframe(data), eager_only=True) result_series = getattr(df["a"], attr)(rhs) assert result_series.name == "a" assert_equal_data({"a": result_series}, {"a": expected}) def test_truediv_same_dims( - constructor_eager: ConstructorEager, request: pytest.FixtureRequest + nw_dataframe: ConstructorEager, request: pytest.FixtureRequest ) -> None: - if "polars" in str(constructor_eager): + if "polars" in str(nw_dataframe): # https://github.com/pola-rs/polars/issues/17760 request.applymarker(pytest.mark.xfail) - s_left = nw.from_native(constructor_eager({"a": [1, 2, 3]}), eager_only=True)["a"] - s_right = nw.from_native(constructor_eager({"a": [2, 2, 1]}), eager_only=True)["a"] + s_left = nw.from_native(nw_dataframe({"a": [1, 2, 3]}), eager_only=True)["a"] + s_right = nw.from_native(nw_dataframe({"a": [2, 2, 1]}), eager_only=True)["a"] result = s_left / s_right assert_equal_data({"a": result}, {"a": [0.5, 1.0, 3.0]}) result = s_left.__rtruediv__(s_right) @@ -160,15 +160,13 @@ def test_truediv_same_dims( @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") @pytest.mark.slow -def test_floordiv( - nw_eager_constructor: ConstructorEager, *, left: int, right: int -) -> None: - if any(x in str(nw_eager_constructor) for x in ["modin", "cudf"]): +def test_floordiv(nw_dataframe: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(nw_dataframe) for x in ["modin", "cudf"]): # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left // right]} - result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_dataframe({"a": [left]}), eager_only=True).select( nw.col("a") // right ) assert_equal_data(result, expected) @@ -177,14 +175,14 @@ def test_floordiv( @pytest.mark.slow @given(left=st.integers(-100, 100), right=st.integers(-100, 100)) @pytest.mark.skipif(PANDAS_VERSION < (2, 0), reason="convert_dtypes not available") -def test_mod(nw_eager_constructor: ConstructorEager, *, left: int, right: int) -> None: - if any(x in str(nw_eager_constructor) for x in ["pandas_pyarrow", "modin", "cudf"]): +def test_mod(nw_dataframe: ConstructorEager, *, left: int, right: int) -> None: + if any(x in str(nw_dataframe) for x in ["pandas_pyarrow", "modin", "cudf"]): # pandas[pyarrow] does not implement mod # modin & cudf are too slow here pytest.skip() assume(right != 0) expected = {"a": [left % right]} - result = nw.from_native(nw_eager_constructor({"a": [left]}), eager_only=True).select( + result = nw.from_native(nw_dataframe({"a": [left]}), eager_only=True).select( nw.col("a") % right ) assert_equal_data(result, expected) @@ -242,16 +240,16 @@ def test_arithmetic_series_left_literal( attr: str, lhs: Any, expected: list[Any], - constructor_eager: ConstructorEager, + nw_dataframe: ConstructorEager, request: pytest.FixtureRequest, ) -> None: if attr == "__mod__" and any( - x in str(constructor_eager) for x in ["pandas_pyarrow", "modin_pyarrow"] + x in str(nw_dataframe) for x in ["pandas_pyarrow", "modin_pyarrow"] ): request.applymarker(pytest.mark.xfail) data = {"a": [1.0, 2.0, 4.0]} - df = nw.from_native(constructor_eager(data)) + df = nw.from_native(nw_dataframe(data)) result = df.select(getattr(lhs, attr)(nw.col("a"))) assert_equal_data(result, {"literal": expected})