From 7f031b02b3c0643965be9aed4c95a3100936ad72 Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Mon, 18 May 2026 12:02:57 +0100 Subject: [PATCH 1/5] ci: bump internal mypy version --- pyproject.toml | 4 ++-- src/narwhals/_arrow/dataframe.py | 1 + src/narwhals/_arrow/series.py | 1 + src/narwhals/_compliant/dataframe.py | 8 ++++++-- src/narwhals/_compliant/group_by.py | 4 ++-- src/narwhals/_compliant/series.py | 3 ++- src/narwhals/_dask/expr.py | 4 ++-- src/narwhals/_duration.py | 3 +-- src/narwhals/_pandas_like/dataframe.py | 2 +- src/narwhals/_polars/dataframe.py | 4 +++- src/narwhals/_polars/namespace.py | 13 +++++++++++-- src/narwhals/_polars/utils.py | 4 ++-- test-plugin/test_plugin/dataframe.py | 4 ++-- tests/expr_and_series/over_test.py | 2 +- tests/v1_test.py | 2 +- 15 files changed, 38 insertions(+), 21 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 1926b21488..b1566a5a9f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,8 +77,8 @@ typing = [ # keep some of these pinned and bump periodically so there's fewer s "pytest", "pandas-stubs==2.3.0.250703", "typing_extensions", - "mypy~=1.15.0", - "pyrefly==0.64.0", + "mypy==2.1.0", + "pyrefly==1.0.0", "pyright", "pyarrow-stubs==19.2", "narwhals[dask]", diff --git a/src/narwhals/_arrow/dataframe.py b/src/narwhals/_arrow/dataframe.py index 44f44c1d95..5e843533d9 100644 --- a/src/narwhals/_arrow/dataframe.py +++ b/src/narwhals/_arrow/dataframe.py @@ -321,6 +321,7 @@ def _select_multi_index( elif is_numpy_array_1d(columns): selector = columns.tolist() else: + columns = cast("Sequence[int]", columns) # help mypy selector = columns return self._with_native(self.native.select(selector)) diff --git a/src/narwhals/_arrow/series.py b/src/narwhals/_arrow/series.py index 19f003f868..208e40216c 100644 --- a/src/narwhals/_arrow/series.py +++ b/src/narwhals/_arrow/series.py @@ -1,5 +1,6 @@ from __future__ import annotations +from collections.abc import Sequence from typing import TYPE_CHECKING, Any, Literal, cast, overload import pyarrow as pa diff --git a/src/narwhals/_compliant/dataframe.py b/src/narwhals/_compliant/dataframe.py index 09d78fcf06..df8c796be6 100644 --- a/src/narwhals/_compliant/dataframe.py +++ b/src/narwhals/_compliant/dataframe.py @@ -2,7 +2,7 @@ from collections.abc import Iterator, Mapping, Sequence, Sized from itertools import chain -from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, overload +from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, cast, overload from narwhals._compliant.typing import ( CompliantDataFrameAny, @@ -50,7 +50,7 @@ import pandas as pd import polars as pl import pyarrow as pa - from typing_extensions import Self + from typing_extensions import Never, Self from narwhals._compliant.group_by import CompliantGroupBy, DataFrameGroupBy from narwhals._compliant.namespace import EagerNamespace @@ -74,6 +74,7 @@ SizeUnit, UniqueKeepStrategy, _2DArray, + _Slice, _SliceIndex, _SliceName, ) @@ -434,12 +435,14 @@ def __getitem__( # noqa: C901, PLR0912 else: compliant = compliant._select_multi_index(columns) elif isinstance(columns, slice): + columns = cast("_Slice[str]", columns) # help mypy compliant = compliant._select_slice_name(columns) elif is_compliant_series(columns): compliant = self._select_multi_name(columns.native) elif is_sequence_like(columns): compliant = self._select_multi_name(columns) else: + columns = cast("Never", columns) # help mypy assert_never(columns) if not is_slice_none(rows): @@ -450,6 +453,7 @@ def __getitem__( # noqa: C901, PLR0912 elif is_compliant_series(rows): compliant = compliant._gather(rows.native) elif is_sized_multi_index_selector(rows): + rows = cast("SizedMultiIndexSelector[Any]", rows) # help mypy compliant = compliant._gather(rows) else: assert_never(rows) diff --git a/src/narwhals/_compliant/group_by.py b/src/narwhals/_compliant/group_by.py index 7ebb9687b7..af58519368 100644 --- a/src/narwhals/_compliant/group_by.py +++ b/src/narwhals/_compliant/group_by.py @@ -1,7 +1,7 @@ from __future__ import annotations from itertools import chain -from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar +from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar, cast from narwhals._compliant.typing import ( CompliantDataFrameT, @@ -161,7 +161,7 @@ def _remap_expr_name( Arguments: name: Name of a `nw.Expr` aggregation method. """ - return cls._REMAP_AGGS.get(name, name) + return cast("NativeAggregationT_co", cls._REMAP_AGGS.get(name, name)) @classmethod def _leaf_name(cls, expr: DepthTrackingExprAny, /) -> NarwhalsAggregation | Any: diff --git a/src/narwhals/_compliant/series.py b/src/narwhals/_compliant/series.py index 077e6a86ad..d340f7e957 100644 --- a/src/narwhals/_compliant/series.py +++ b/src/narwhals/_compliant/series.py @@ -347,7 +347,8 @@ class EagerSeriesStructNamespace( # type: ignore[misc] ): ... -class EagerSeriesHist(Protocol[NativeSeriesT, _CountsT_co]): +# mypy says: `Covariant type variable "_CountsT_co" used in protocol where invariant one is expected` +class EagerSeriesHist(Protocol[NativeSeriesT, _CountsT_co]): # type: ignore[misc] _series: EagerSeries[NativeSeriesT] _breakpoint: bool _data: HistData[NativeSeriesT, _CountsT_co] diff --git a/src/narwhals/_dask/expr.py b/src/narwhals/_dask/expr.py index b6e5d4d844..3961b5ee7e 100644 --- a/src/narwhals/_dask/expr.py +++ b/src/narwhals/_dask/expr.py @@ -715,5 +715,5 @@ def dt(self) -> DaskExprDateTimeNamespace: last = not_implemented() # namespaces - list: not_implemented = not_implemented() # type: ignore[assignment] - struct: not_implemented = not_implemented() # type: ignore[assignment] + list: Any = not_implemented() + struct: Any = not_implemented() diff --git a/src/narwhals/_duration.py b/src/narwhals/_duration.py index 40e330a276..b9350cf41c 100644 --- a/src/narwhals/_duration.py +++ b/src/narwhals/_duration.py @@ -57,8 +57,7 @@ def to_timedelta( msg = f"Creating timedelta with {self.unit} unit is not supported." raise NotImplementedError(msg) kwd = UNIT_TO_TIMEDELTA[self.unit] - # error: Keywords must be strings (bad mypy) - return dt.timedelta(**{kwd: self.multiple}) # type: ignore[misc] + return dt.timedelta(**{kwd: self.multiple}) @classmethod def parse(cls, every: str) -> Interval: diff --git a/src/narwhals/_pandas_like/dataframe.py b/src/narwhals/_pandas_like/dataframe.py index 23b17796df..edc8a90034 100644 --- a/src/narwhals/_pandas_like/dataframe.py +++ b/src/narwhals/_pandas_like/dataframe.py @@ -1180,7 +1180,7 @@ def pivot( remapped = self._pivot_remap_column_names( columns, n_on=len(on), n_values=len(values), separator=separator ) - result.columns = remapped # type: ignore[assignment] + result.columns = remapped result.columns.names = [""] return self._with_native(result.reset_index()) diff --git a/src/narwhals/_polars/dataframe.py b/src/narwhals/_polars/dataframe.py index 3c746c188c..8be857f94b 100644 --- a/src/narwhals/_polars/dataframe.py +++ b/src/narwhals/_polars/dataframe.py @@ -59,6 +59,7 @@ SingleIndexSelector, UniqueKeepStrategy, _2DArray, + _Slice, ) T = TypeVar("T") @@ -222,7 +223,7 @@ def join( return self._with_native( self.native.join( other=other.native, - how=how_native, # type: ignore[arg-type] + how=how_native, left_on=left_on, right_on=right_on, suffix=suffix, @@ -495,6 +496,7 @@ def __getitem__( # noqa: C901, PLR0912 else: native = native[:, columns] elif isinstance(columns, slice): + columns = cast("_Slice[str]", columns) # help mypy native = native.select( self.columns[ slice(*convert_str_slice_to_int_slice(columns, self.columns)) diff --git a/src/narwhals/_polars/namespace.py b/src/narwhals/_polars/namespace.py index e7e0f2692c..917555bf94 100644 --- a/src/narwhals/_polars/namespace.py +++ b/src/narwhals/_polars/namespace.py @@ -22,7 +22,14 @@ from narwhals._polars.dataframe import Method, PolarsDataFrame, PolarsLazyFrame from narwhals._polars.typing import FrameT from narwhals._utils import Version, _LimitedContext - from narwhals.typing import Into1DArray, IntoDType, IntoSchema, TimeUnit, _2DArray + from narwhals.typing import ( + Into1DArray, + IntoDType, + IntoSchema, + NonNestedDType, + TimeUnit, + _2DArray, + ) class PolarsNamespace: @@ -239,7 +246,9 @@ def __init__(self, context: _LimitedContext, /) -> None: def by_dtype(self, dtypes: Iterable[DType]) -> PolarsExpr: native_dtypes = [ - narwhals_to_native_dtype(dtype, self._version).__class__ + narwhals_to_native_dtype( + cast("type[NonNestedDType]", dtype), self._version + ).__class__ if isinstance(dtype, type) and issubclass(dtype, DType) else narwhals_to_native_dtype(dtype, self._version) for dtype in dtypes diff --git a/src/narwhals/_polars/utils.py b/src/narwhals/_polars/utils.py index 75a61b0d19..553de13114 100644 --- a/src/narwhals/_polars/utils.py +++ b/src/narwhals/_polars/utils.py @@ -2,7 +2,7 @@ import abc from functools import lru_cache -from typing import TYPE_CHECKING, Any, ClassVar, Final, Protocol, TypeVar, overload +from typing import TYPE_CHECKING, Any, ClassVar, Final, Protocol, TypeVar, cast, overload import polars as pl @@ -73,7 +73,7 @@ def extract_native(obj: _StoresNative[NativeT]) -> NativeT: ... @overload def extract_native(obj: T) -> T: ... def extract_native(obj: _StoresNative[NativeT] | T) -> NativeT | T: - return obj.native if _is_compliant_polars(obj) else obj + return obj.native if _is_compliant_polars(obj) else cast("T", obj) def _is_compliant_polars( diff --git a/test-plugin/test_plugin/dataframe.py b/test-plugin/test_plugin/dataframe.py index d7f1f237c7..56bc928cf7 100644 --- a/test-plugin/test_plugin/dataframe.py +++ b/test-plugin/test_plugin/dataframe.py @@ -47,10 +47,10 @@ def _with_version(self, version: Version) -> Self: __native_namespace__ = not_implemented() # Properties - schema = not_implemented() # type: ignore[assignment] + schema: Any = not_implemented() # Static - _is_native = not_implemented() # type: ignore[assignment] + _is_native = not_implemented() # Helpers _iter_columns = not_implemented() diff --git a/tests/expr_and_series/over_test.py b/tests/expr_and_series/over_test.py index 741054936a..31b55f08d2 100644 --- a/tests/expr_and_series/over_test.py +++ b/tests/expr_and_series/over_test.py @@ -245,7 +245,7 @@ def test_over_anonymous_cumulative( context = ( pytest.raises(NotImplementedError) if df.implementation.is_pyarrow() - else pytest.raises(KeyError) # type: ignore[arg-type] + else pytest.raises(KeyError) if df.implementation.is_modin() or (df.implementation.is_pandas() and PANDAS_VERSION < (1, 3)) # TODO(unassigned): bug in old pandas + modin. diff --git a/tests/v1_test.py b/tests/v1_test.py index bfdfd51efa..1e2a18842d 100644 --- a/tests/v1_test.py +++ b/tests/v1_test.py @@ -591,7 +591,7 @@ def __dataframe__(self) -> None: # pragma: no cover mockdf = MockDf() result = nw_v1.from_native(mockdf, eager_only=True, strict=False) - assert result is mockdf + assert result is mockdf # type: ignore[comparison-overlap] def test_from_native_lazyframe() -> None: From 6610c5e70095fb4b6feb232dc2603d64ce4a747e Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Mon, 18 May 2026 13:39:43 +0100 Subject: [PATCH 2/5] cvg --- src/narwhals/_compliant/dataframe.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/narwhals/_compliant/dataframe.py b/src/narwhals/_compliant/dataframe.py index df8c796be6..4be3e3c29a 100644 --- a/src/narwhals/_compliant/dataframe.py +++ b/src/narwhals/_compliant/dataframe.py @@ -442,7 +442,7 @@ def __getitem__( # noqa: C901, PLR0912 elif is_sequence_like(columns): compliant = self._select_multi_name(columns) else: - columns = cast("Never", columns) # help mypy + columns = cast("Never", columns) # help mypy # pragma: no cover assert_never(columns) if not is_slice_none(rows): From ad27dfbc17af79b28694297f512eec6106a419f7 Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 May 2026 10:18:29 +0100 Subject: [PATCH 3/5] define MYPY constant --- pyproject.toml | 1 + src/narwhals/_arrow/dataframe.py | 7 +++++-- src/narwhals/_arrow/series.py | 1 - src/narwhals/_compliant/dataframe.py | 18 +++++++++++++----- src/narwhals/_compliant/group_by.py | 5 +++-- src/narwhals/_polars/namespace.py | 15 +++------------ tests/v1_test.py | 1 + 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index db700fbb88..621267504c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -386,6 +386,7 @@ ignore = [ "../../../**/Lib", # stdlib "../../../**/typeshed*" # typeshed-fallback ] +defineConstant = { "MYPY" = false } [tool.pyrefly] search-path = ["src", "."] diff --git a/src/narwhals/_arrow/dataframe.py b/src/narwhals/_arrow/dataframe.py index 5e843533d9..e6330a6db4 100644 --- a/src/narwhals/_arrow/dataframe.py +++ b/src/narwhals/_arrow/dataframe.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections.abc import Collection, Iterator, Mapping, Sequence -from typing import TYPE_CHECKING, Any, Literal, cast, overload +from typing import TYPE_CHECKING, Any, Final, Literal, cast, overload import pyarrow as pa import pyarrow.compute as pc @@ -77,6 +77,8 @@ "full outer", ] +MYPY: Final = False + class ArrowDataFrame( EagerDataFrame["ArrowSeries", "ArrowExpr", "pa.Table", "ChunkedArrayAny"] @@ -321,7 +323,8 @@ def _select_multi_index( elif is_numpy_array_1d(columns): selector = columns.tolist() else: - columns = cast("Sequence[int]", columns) # help mypy + if MYPY: + columns = cast("Sequence[int]", columns) selector = columns return self._with_native(self.native.select(selector)) diff --git a/src/narwhals/_arrow/series.py b/src/narwhals/_arrow/series.py index 208e40216c..19f003f868 100644 --- a/src/narwhals/_arrow/series.py +++ b/src/narwhals/_arrow/series.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Sequence from typing import TYPE_CHECKING, Any, Literal, cast, overload import pyarrow as pa diff --git a/src/narwhals/_compliant/dataframe.py b/src/narwhals/_compliant/dataframe.py index 4be3e3c29a..280f71d1b7 100644 --- a/src/narwhals/_compliant/dataframe.py +++ b/src/narwhals/_compliant/dataframe.py @@ -2,7 +2,7 @@ from collections.abc import Iterator, Mapping, Sequence, Sized from itertools import chain -from typing import TYPE_CHECKING, Any, Literal, Protocol, TypeVar, cast, overload +from typing import TYPE_CHECKING, Any, Final, Literal, Protocol, TypeVar, cast, overload from narwhals._compliant.typing import ( CompliantDataFrameAny, @@ -50,7 +50,7 @@ import pandas as pd import polars as pl import pyarrow as pa - from typing_extensions import Never, Self + from typing_extensions import Self from narwhals._compliant.group_by import CompliantGroupBy, DataFrameGroupBy from narwhals._compliant.namespace import EagerNamespace @@ -81,6 +81,8 @@ Incomplete: TypeAlias = Any +MYPY: Final = False + __all__ = ["CompliantDataFrame", "CompliantFrame", "CompliantLazyFrame", "EagerDataFrame"] T = TypeVar("T") @@ -435,14 +437,18 @@ def __getitem__( # noqa: C901, PLR0912 else: compliant = compliant._select_multi_index(columns) elif isinstance(columns, slice): - columns = cast("_Slice[str]", columns) # help mypy + if MYPY: + # https://github.com/python/mypy/issues/21508 + columns = cast("_Slice[str]", columns) compliant = compliant._select_slice_name(columns) elif is_compliant_series(columns): compliant = self._select_multi_name(columns.native) elif is_sequence_like(columns): compliant = self._select_multi_name(columns) + elif MYPY: + # https://github.com/python/mypy/issues/21508 + pass else: - columns = cast("Never", columns) # help mypy # pragma: no cover assert_never(columns) if not is_slice_none(rows): @@ -453,7 +459,9 @@ def __getitem__( # noqa: C901, PLR0912 elif is_compliant_series(rows): compliant = compliant._gather(rows.native) elif is_sized_multi_index_selector(rows): - rows = cast("SizedMultiIndexSelector[Any]", rows) # help mypy + if MYPY: + # https://github.com/python/mypy/issues/21508 + rows = cast("SizedMultiIndexSelector[Any]", rows) # help mypy compliant = compliant._gather(rows) else: assert_never(rows) diff --git a/src/narwhals/_compliant/group_by.py b/src/narwhals/_compliant/group_by.py index af58519368..84d39c2a52 100644 --- a/src/narwhals/_compliant/group_by.py +++ b/src/narwhals/_compliant/group_by.py @@ -1,7 +1,7 @@ from __future__ import annotations from itertools import chain -from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar, cast +from typing import TYPE_CHECKING, Any, ClassVar, Protocol, TypeVar from narwhals._compliant.typing import ( CompliantDataFrameT, @@ -161,7 +161,8 @@ def _remap_expr_name( Arguments: name: Name of a `nw.Expr` aggregation method. """ - return cast("NativeAggregationT_co", cls._REMAP_AGGS.get(name, name)) + result: NativeAggregationT_co = cls._REMAP_AGGS.get(name, name) + return result @classmethod def _leaf_name(cls, expr: DepthTrackingExprAny, /) -> NarwhalsAggregation | Any: diff --git a/src/narwhals/_polars/namespace.py b/src/narwhals/_polars/namespace.py index 917555bf94..9b596f8f4b 100644 --- a/src/narwhals/_polars/namespace.py +++ b/src/narwhals/_polars/namespace.py @@ -22,14 +22,7 @@ from narwhals._polars.dataframe import Method, PolarsDataFrame, PolarsLazyFrame from narwhals._polars.typing import FrameT from narwhals._utils import Version, _LimitedContext - from narwhals.typing import ( - Into1DArray, - IntoDType, - IntoSchema, - NonNestedDType, - TimeUnit, - _2DArray, - ) + from narwhals.typing import Into1DArray, IntoDType, IntoSchema, TimeUnit, _2DArray class PolarsNamespace: @@ -244,11 +237,9 @@ class PolarsSelectorNamespace: def __init__(self, context: _LimitedContext, /) -> None: self._version = context._version - def by_dtype(self, dtypes: Iterable[DType]) -> PolarsExpr: + def by_dtype(self, dtypes: Iterable[IntoDType]) -> PolarsExpr: native_dtypes = [ - narwhals_to_native_dtype( - cast("type[NonNestedDType]", dtype), self._version - ).__class__ + narwhals_to_native_dtype(dtype, self._version).__class__ if isinstance(dtype, type) and issubclass(dtype, DType) else narwhals_to_native_dtype(dtype, self._version) for dtype in dtypes diff --git a/tests/v1_test.py b/tests/v1_test.py index 1e2a18842d..21c0ce1826 100644 --- a/tests/v1_test.py +++ b/tests/v1_test.py @@ -591,6 +591,7 @@ def __dataframe__(self) -> None: # pragma: no cover mockdf = MockDf() result = nw_v1.from_native(mockdf, eager_only=True, strict=False) + # mypy issue? assert result is mockdf # type: ignore[comparison-overlap] From 698288de52946a730097be14be26b5ddbaa96952 Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 May 2026 10:41:21 +0100 Subject: [PATCH 4/5] if MYPY --- pyproject.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/pyproject.toml b/pyproject.toml index 621267504c..4dad0480a6 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -322,6 +322,7 @@ exclude_also = [ 'if "(cudf|modin|pyspark|ibis)" in', "if not .*.is_pandas", "if is_ibis_table", + "if MYPY", "except ModuleNotFoundError", 'request.applymarker\(pytest.mark.xfail', 'backend_version <', From ec15f071d80258ec0003eada55b912509fca52fa Mon Sep 17 00:00:00 2001 From: MarcoGorelli <33491632+MarcoGorelli@users.noreply.github.com> Date: Tue, 19 May 2026 11:11:13 +0100 Subject: [PATCH 5/5] split conditions --- src/narwhals/_arrow/dataframe.py | 4 ++-- src/narwhals/_compliant/dataframe.py | 15 ++++++++------- src/narwhals/_polars/dataframe.py | 16 ++++++++-------- 3 files changed, 18 insertions(+), 17 deletions(-) diff --git a/src/narwhals/_arrow/dataframe.py b/src/narwhals/_arrow/dataframe.py index e6330a6db4..3e5297d5a7 100644 --- a/src/narwhals/_arrow/dataframe.py +++ b/src/narwhals/_arrow/dataframe.py @@ -322,9 +322,9 @@ def _select_multi_index( # **Doesn't accept `ndarray`** elif is_numpy_array_1d(columns): selector = columns.tolist() + elif MYPY: + selector = columns # type: ignore[assignment] else: - if MYPY: - columns = cast("Sequence[int]", columns) selector = columns return self._with_native(self.native.select(selector)) diff --git a/src/narwhals/_compliant/dataframe.py b/src/narwhals/_compliant/dataframe.py index 280f71d1b7..912dc5afb5 100644 --- a/src/narwhals/_compliant/dataframe.py +++ b/src/narwhals/_compliant/dataframe.py @@ -2,7 +2,7 @@ from collections.abc import Iterator, Mapping, Sequence, Sized from itertools import chain -from typing import TYPE_CHECKING, Any, Final, Literal, Protocol, TypeVar, cast, overload +from typing import TYPE_CHECKING, Any, Final, Literal, Protocol, TypeVar, overload from narwhals._compliant.typing import ( CompliantDataFrameAny, @@ -74,7 +74,6 @@ SizeUnit, UniqueKeepStrategy, _2DArray, - _Slice, _SliceIndex, _SliceName, ) @@ -439,8 +438,9 @@ def __getitem__( # noqa: C901, PLR0912 elif isinstance(columns, slice): if MYPY: # https://github.com/python/mypy/issues/21508 - columns = cast("_Slice[str]", columns) - compliant = compliant._select_slice_name(columns) + compliant = compliant._select_slice_name(columns) # type: ignore[arg-type] + else: + compliant = compliant._select_slice_name(columns) elif is_compliant_series(columns): compliant = self._select_multi_name(columns.native) elif is_sequence_like(columns): @@ -459,10 +459,11 @@ def __getitem__( # noqa: C901, PLR0912 elif is_compliant_series(rows): compliant = compliant._gather(rows.native) elif is_sized_multi_index_selector(rows): - if MYPY: + if MYPY: # noqa: SIM108 # https://github.com/python/mypy/issues/21508 - rows = cast("SizedMultiIndexSelector[Any]", rows) # help mypy - compliant = compliant._gather(rows) + compliant = compliant._gather(rows) # type: ignore[arg-type] + else: + compliant = compliant._gather(rows) else: assert_never(rows) diff --git a/src/narwhals/_polars/dataframe.py b/src/narwhals/_polars/dataframe.py index 8be857f94b..9b806e3635 100644 --- a/src/narwhals/_polars/dataframe.py +++ b/src/narwhals/_polars/dataframe.py @@ -1,7 +1,7 @@ from __future__ import annotations from collections.abc import Iterator, Mapping, Sequence, Sized -from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar, cast, overload +from typing import TYPE_CHECKING, Any, Final, Generic, Literal, TypeVar, cast, overload import polars as pl @@ -59,12 +59,13 @@ SingleIndexSelector, UniqueKeepStrategy, _2DArray, - _Slice, ) T = TypeVar("T") R = TypeVar("R") +MYPY: Final = False + Method: TypeAlias = "Callable[..., R]" """Generic alias representing all methods implemented via `__getattr__`. @@ -496,12 +497,11 @@ def __getitem__( # noqa: C901, PLR0912 else: native = native[:, columns] elif isinstance(columns, slice): - columns = cast("_Slice[str]", columns) # help mypy - native = native.select( - self.columns[ - slice(*convert_str_slice_to_int_slice(columns, self.columns)) - ] - ) + if MYPY: + int_slice = convert_str_slice_to_int_slice(columns, self.columns) # type: ignore[arg-type] + else: + int_slice = convert_str_slice_to_int_slice(columns, self.columns) + native = native.select(self.columns[slice(*int_slice)]) elif is_compliant_series(columns): native = native.select(columns.native.to_list()) elif is_sequence_like(columns):