Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 58 additions & 40 deletions narwhals/stable/v1/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from typing import Iterable
from typing import Literal
from typing import Sequence
from typing import TypeVar
from typing import overload
from warnings import warn

Expand Down Expand Up @@ -86,6 +85,7 @@
from typing import Mapping

from typing_extensions import Self
from typing_extensions import TypeVar

from narwhals.dtypes import DType
from narwhals.functions import ArrowStreamExportable
Expand All @@ -95,7 +95,13 @@
from narwhals.typing import _1DArray
from narwhals.typing import _2DArray

T = TypeVar("T")
IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries", default=Any)
T = TypeVar("T", default=Any)
else:
from typing import TypeVar

IntoSeriesT = TypeVar("IntoSeriesT", bound="IntoSeries")
T = TypeVar("T")
Comment on lines +98 to +104
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using PEP 696 is intended to limit the impact of the change downstream.

Code that currently uses v1.Series should fall back to the default v1.Series[Any].
Instead of appearing as v1.Series[Unknown].

I'm not sure if that was a problem in #1412, since the logs have expired https://github.com/narwhals-dev/narwhals/actions/runs/11932852152/job/33258672137?pr=1412



class DataFrame(NwDataFrame[IntoDataFrameT]):
Expand Down Expand Up @@ -127,7 +133,7 @@ class DataFrame(NwDataFrame[IntoDataFrameT]):
# annotations are correct.

@property
def _series(self: Self) -> type[Series]:
def _series(self: Self) -> type[Series[Any]]:
return Series

@property
Expand All @@ -138,7 +144,7 @@ def _lazyframe(self: Self) -> type[LazyFrame[Any]]:
def __getitem__( # type: ignore[overload-overlap]
self: Self,
item: str | tuple[slice | Sequence[int] | _1DArray, int | str],
) -> Series: ...
) -> Series[Any]: ...
@overload
def __getitem__(
self: Self,
Expand Down Expand Up @@ -192,16 +198,18 @@ def lazy(
# Not sure what mypy is complaining about, probably some fancy
# thing that I need to understand category theory for
@overload # type: ignore[override]
def to_dict(self: Self, *, as_series: Literal[True] = ...) -> dict[str, Series]: ...
def to_dict(
self: Self, *, as_series: Literal[True] = ...
) -> dict[str, Series[Any]]: ...
@overload
def to_dict(self: Self, *, as_series: Literal[False]) -> dict[str, list[Any]]: ...
@overload
def to_dict(
self: Self, *, as_series: bool
) -> dict[str, Series] | dict[str, list[Any]]: ...
) -> dict[str, Series[Any]] | dict[str, list[Any]]: ...
def to_dict(
self: Self, *, as_series: bool = True
) -> dict[str, Series] | dict[str, list[Any]]:
) -> dict[str, Series[Any]] | dict[str, list[Any]]:
"""Convert DataFrame to a dictionary mapping column name to values.

Arguments:
Expand All @@ -213,15 +221,15 @@ def to_dict(
"""
return super().to_dict(as_series=as_series) # type: ignore[return-value]

def is_duplicated(self: Self) -> Series:
def is_duplicated(self: Self) -> Series[Any]:
r"""Get a mask of all duplicated rows in this DataFrame.

Returns:
A new Series.
"""
return super().is_duplicated() # type: ignore[return-value]

def is_unique(self: Self) -> Series:
def is_unique(self: Self) -> Series[Any]:
r"""Get a mask of all unique rows in this DataFrame.

Returns:
Expand Down Expand Up @@ -341,7 +349,7 @@ def tail(self, n: int = 5) -> Self: # pragma: no cover
return super().tail(n)


class Series(NwSeries[Any]):
class Series(NwSeries[IntoSeriesT]):
"""Narwhals Series, backed by a native series.

!!! warning
Expand Down Expand Up @@ -1102,16 +1110,20 @@ def _stableify(obj: NwDataFrame[IntoFrameT]) -> DataFrame[IntoFrameT]: ...
@overload
def _stableify(obj: NwLazyFrame[IntoFrameT]) -> LazyFrame[IntoFrameT]: ...
@overload
def _stableify(obj: NwSeries[Any]) -> Series: ...
def _stableify(obj: NwSeries[IntoSeriesT]) -> Series[IntoSeriesT]: ...
@overload
def _stableify(obj: NwExpr) -> Expr: ...
@overload
def _stableify(obj: Any) -> Any: ...


def _stableify(
obj: NwDataFrame[IntoFrameT] | NwLazyFrame[IntoFrameT] | NwSeries[Any] | NwExpr | Any,
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series | Expr | Any:
obj: NwDataFrame[IntoFrameT]
| NwLazyFrame[IntoFrameT]
| NwSeries[IntoSeriesT]
| NwExpr
| Any,
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series[IntoSeriesT] | Expr | Any:
if isinstance(obj, NwDataFrame):
return DataFrame(
obj._compliant_frame._change_version(Version.V1),
Expand All @@ -1134,26 +1146,26 @@ def _stableify(

@overload
def from_native(
native_object: IntoDataFrameT | IntoSeries,
native_object: IntoDataFrameT | IntoSeriesT,
*,
strict: Literal[False],
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[True],
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[IntoDataFrameT] | Series: ...
) -> DataFrame[IntoDataFrameT] | Series[IntoSeriesT]: ...


@overload
def from_native(
native_object: IntoDataFrameT | IntoSeries,
native_object: IntoDataFrameT | IntoSeriesT,
*,
strict: Literal[False],
eager_only: Literal[True],
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[IntoDataFrameT] | Series: ...
) -> DataFrame[IntoDataFrameT] | Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1206,26 +1218,26 @@ def from_native(

@overload
def from_native(
native_object: IntoFrameT | IntoSeries,
native_object: IntoFrameT | IntoSeriesT,
*,
strict: Literal[False],
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series: ...
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series[IntoSeriesT]: ...


@overload
def from_native(
native_object: IntoSeries,
native_object: IntoSeriesT,
*,
strict: Literal[False],
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[True],
allow_series: None = ...,
) -> Series: ...
) -> Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1285,19 +1297,19 @@ def from_native(
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[Any] | LazyFrame[Any] | Series: ...
) -> DataFrame[Any] | LazyFrame[Any] | Series[Any]: ...


@overload
def from_native(
native_object: IntoSeries | Any, # remain `Any` for downstream compatibility
native_object: IntoSeriesT,
*,
strict: Literal[True] = ...,
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[True],
allow_series: None = ...,
) -> Series: ...
) -> Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1326,14 +1338,14 @@ def from_native(

@overload
def from_native(
native_object: IntoDataFrameT | IntoSeries,
native_object: IntoDataFrameT | IntoSeriesT,
*,
pass_through: Literal[True],
eager_only: Literal[True],
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[IntoDataFrameT] | Series: ...
) -> DataFrame[IntoDataFrameT] | Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1386,26 +1398,26 @@ def from_native(

@overload
def from_native(
native_object: IntoFrameT | IntoSeries,
native_object: IntoFrameT | IntoSeriesT,
*,
pass_through: Literal[True],
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series: ...
) -> DataFrame[IntoFrameT] | LazyFrame[IntoFrameT] | Series[IntoSeriesT]: ...


@overload
def from_native(
native_object: IntoSeries,
native_object: IntoSeriesT,
*,
pass_through: Literal[True],
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[True],
allow_series: None = ...,
) -> Series: ...
) -> Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1465,19 +1477,19 @@ def from_native(
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[False] = ...,
allow_series: Literal[True],
) -> DataFrame[Any] | LazyFrame[Any] | Series: ...
) -> DataFrame[Any] | LazyFrame[Any] | Series[Any]: ...


@overload
def from_native(
native_object: IntoSeries,
native_object: IntoSeriesT,
*,
pass_through: Literal[False] = ...,
eager_only: Literal[False] = ...,
eager_or_interchange_only: Literal[False] = ...,
series_only: Literal[True],
allow_series: None = ...,
) -> Series: ...
) -> Series[IntoSeriesT]: ...


@overload
Expand Down Expand Up @@ -1506,15 +1518,15 @@ def from_native(


def from_native(
native_object: IntoFrameT | IntoFrame | IntoSeries | T,
native_object: IntoFrameT | IntoFrame | IntoSeriesT | IntoSeries | T,
*,
strict: bool | None = None,
pass_through: bool | None = None,
eager_only: bool = False,
eager_or_interchange_only: bool = False,
series_only: bool = False,
allow_series: bool | None = None,
) -> LazyFrame[IntoFrameT] | DataFrame[IntoFrameT] | Series | T:
) -> LazyFrame[IntoFrameT] | DataFrame[IntoFrameT] | Series[IntoSeriesT] | T:
"""Convert `native_object` to Narwhals Dataframe, Lazyframe, or Series.

Arguments:
Expand Down Expand Up @@ -1595,7 +1607,9 @@ def to_native(
narwhals_object: LazyFrame[IntoFrameT], *, strict: Literal[True] = ...
) -> IntoFrameT: ...
@overload
def to_native(narwhals_object: Series, *, strict: Literal[True] = ...) -> Any: ...
def to_native(
narwhals_object: Series[IntoSeriesT], *, strict: Literal[True] = ...
) -> IntoSeriesT: ...
@overload
def to_native(narwhals_object: Any, *, strict: bool) -> Any: ...
@overload
Expand All @@ -1607,17 +1621,21 @@ def to_native(
narwhals_object: LazyFrame[IntoFrameT], *, pass_through: Literal[False] = ...
) -> IntoFrameT: ...
@overload
def to_native(narwhals_object: Series, *, pass_through: Literal[False] = ...) -> Any: ...
def to_native(
narwhals_object: Series[IntoSeriesT], *, pass_through: Literal[False] = ...
) -> IntoSeriesT: ...
@overload
def to_native(narwhals_object: Any, *, pass_through: bool) -> Any: ...


def to_native(
narwhals_object: DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT] | Series,
narwhals_object: DataFrame[IntoDataFrameT]
| LazyFrame[IntoFrameT]
| Series[IntoSeriesT],
*,
strict: bool | None = None,
pass_through: bool | None = None,
) -> IntoFrameT | Any:
) -> IntoFrameT | IntoSeriesT | Any:
"""Convert Narwhals object to native one.

Arguments:
Expand Down Expand Up @@ -2124,7 +2142,7 @@ def new_series(
dtype: DType | type[DType] | None = None,
*,
native_namespace: ModuleType,
) -> Series:
) -> Series[Any]:
"""Instantiate Narwhals Series from iterable (e.g. list or array).

Arguments:
Expand Down
Loading
Loading