Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
d5a126d
fix(typing): Huuuuuuuge progress
dangotbanned Sep 12, 2025
39bb6b3
test(typing): Add `pa.ChunkedArray` into the mix
dangotbanned Sep 12, 2025
c7cf5ae
test: Rename variables
dangotbanned Sep 12, 2025
6f56dc0
test: Cover w/ `pass_through=True` as well
dangotbanned Sep 12, 2025
d72ce2d
test: Use `assert_type` and runtime checks
dangotbanned Sep 12, 2025
94029ed
test: rename test
dangotbanned Sep 12, 2025
0358cc9
test: Insane `LazyFrame` coverage
dangotbanned Sep 12, 2025
43ceb3f
revert: wont be using that one
dangotbanned Sep 12, 2025
ceaf9e7
refactor(typing): Factor out another pair
dangotbanned Sep 12, 2025
d988a24
refactor(typing): Add single `pass_through` case
dangotbanned Sep 12, 2025
cc5588b
revert: never used them
dangotbanned Sep 12, 2025
1cab6d0
refactor: Invert `NotRequired` -> `Required`
dangotbanned Sep 12, 2025
ff6258d
refactor: Rename all `TypedDict`s
dangotbanned Sep 12, 2025
a0095b1
style: Remove whitespace
dangotbanned Sep 12, 2025
06d74a3
Merge remote-tracking branch 'upstream/main' into from-native-overloads
dangotbanned Sep 12, 2025
c02ab37
Merge branch 'main' into from-native-overloads
dangotbanned Sep 13, 2025
5b6ca5f
Merge branch 'main' into from-native-overloads
dangotbanned Oct 6, 2025
4142e43
Merge remote-tracking branch 'upstream/main' into from-native-overloads
dangotbanned Oct 20, 2025
2e7a0ae
chore: fix merge conflicts
dangotbanned Oct 20, 2025
435beb4
refactor: Move new `TypedDict`s to `_translate.py`
dangotbanned Oct 20, 2025
0605936
fix(typing): More gracefully handle narwhals in overloads
dangotbanned Oct 20, 2025
67bb52f
revert: Remove now-unused `kwds`
dangotbanned Oct 20, 2025
fd7ab16
refactor(typing): Update `v2`
dangotbanned Oct 20, 2025
9a8c025
refactor(DRAFT): Start shrinking `v1`
dangotbanned Oct 20, 2025
c61af03
refactor(typing): Add `AllowAny` variants
dangotbanned Oct 20, 2025
252bcdb
refactor(typing): Add `AllowSeries` variants
dangotbanned Oct 20, 2025
c887618
refactor(typing): Add `OnlySeries` variants
dangotbanned Oct 20, 2025
99527d5
refactor(typing): Add `ExcludeSeries` variants
dangotbanned Oct 20, 2025
1dc56f0
refactor(typing): Add `AllowLazy` variants
dangotbanned Oct 20, 2025
10e7ddf
refactor(typing): Add `OnlyEagerOrInterchange` variants
dangotbanned Oct 20, 2025
1c498aa
chore: remove notes
dangotbanned Oct 20, 2025
4e37df6
chore: Fix those imports for `v1` too
dangotbanned Oct 20, 2025
f372696
oop missed a spot
dangotbanned Oct 20, 2025
459598f
chore: remove some comments
dangotbanned Oct 20, 2025
58590e4
Merge remote-tracking branch 'upstream/main' into from-native-overloads
dangotbanned Oct 20, 2025
bd90c1f
Merge branch 'main' into from-native-overloads
dangotbanned Oct 23, 2025
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
5 changes: 4 additions & 1 deletion narwhals/_native.py
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,8 @@ def columns(self) -> Any: ...
def join(self, *args: Any, **kwargs: Any) -> Any: ...


class NativeDataFrame(Sized, NativeFrame, Protocol): ...
class NativeDataFrame(Sized, NativeFrame, Protocol):
def drop(self, *args: Any, **kwargs: Any) -> Any: ...


class NativeLazyFrame(NativeFrame, Protocol):
Expand All @@ -199,6 +200,8 @@ def explain(self, *args: Any, **kwargs: Any) -> Any: ...

class NativeSeries(Sized, Iterable[Any], Protocol):
def filter(self, *args: Any, **kwargs: Any) -> Any: ...
def value_counts(self, *args: Any, **kwargs: Any) -> Any: ...
def unique(self, *args: Any, **kwargs: Any) -> Any: ...


class _BasePandasLike(Sized, Protocol):
Expand Down
145 changes: 140 additions & 5 deletions narwhals/_translate.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
"""[Protocols] defining conversion methods between representations.
"""[Protocols] defining conversion methods between representations, and related [structural] typing.

These come in 3 flavors and are [generic] to promote reuse.
The protocols come in 3 flavors and are [generic] to promote reuse.

The following examples use the placeholder types `Narwhal` and `Other`:
These examples use the placeholder types `Narwhal` and `Other`:
- `Narwhal`: some class written in `narwhals`.
- `Other`: any other class, could be native, compliant, or a builtin.

Expand Down Expand Up @@ -53,6 +53,7 @@ class OtherConvertible(

[Protocols]: https://typing.python.org/en/latest/spec/protocol.html
[generic]: https://typing.python.org/en/latest/spec/generics.html
[structural]: https://typing.python.org/en/latest/spec/glossary.html#term-structural
[upstream signature]: https://numpy.org/doc/stable/user/basics.interoperability.html#the-array-method
[positional-only]: https://peps.python.org/pep-0570/
[moist]: https://mypy.readthedocs.io/en/stable/generics.html#variance-of-generic-types
Expand All @@ -63,13 +64,13 @@ class OtherConvertible(
from __future__ import annotations

from collections.abc import Iterable, Mapping
from typing import TYPE_CHECKING, Any, Protocol
from typing import TYPE_CHECKING, Any, Literal, Protocol, TypedDict

from narwhals._typing_compat import TypeVar

if TYPE_CHECKING:
import pyarrow as pa
from typing_extensions import Self, TypeAlias, TypeIs
from typing_extensions import Required, Self, TypeAlias, TypeIs


class ArrowStreamExportable(Protocol):
Expand Down Expand Up @@ -184,3 +185,137 @@ class ToNarwhals(Protocol[ToNarwhalsT_co]):
def to_narwhals(self) -> ToNarwhalsT_co:
"""Convert into public representation."""
...


class _ExcludeSeries(TypedDict, total=False):
eager_only: bool
series_only: Literal[False]
allow_series: Literal[False] | None


class ExcludeSeries(_ExcludeSeries, total=False):
pass_through: bool


class ExcludeSeriesV1(_ExcludeSeries, total=False):
pass_through: bool | None
eager_or_interchange_only: Literal[False]


class ExcludeSeriesStrictV1(_ExcludeSeries, total=False):
strict: bool | None
eager_or_interchange_only: Literal[False]


class _AllowSeries(TypedDict, total=False):
eager_only: bool
series_only: Literal[False]
allow_series: Required[Literal[True]]


class AllowSeries(_AllowSeries, total=False):
pass_through: bool


class AllowSeriesV1(_AllowSeries, total=False):
pass_through: bool | None
eager_or_interchange_only: Literal[False]


class AllowSeriesStrictV1(_AllowSeries, total=False):
strict: bool | None
eager_or_interchange_only: Literal[False]


class _OnlySeries(TypedDict, total=False):
eager_only: bool
series_only: Required[Literal[True]]
allow_series: bool | None


class OnlySeries(_OnlySeries, total=False):
pass_through: bool


class OnlySeriesV1(_OnlySeries, total=False):
pass_through: bool | None
eager_or_interchange_only: Literal[False]


class OnlySeriesStrictV1(_OnlySeries, total=False):
strict: bool | None
eager_or_interchange_only: Literal[False]


class _OnlyEagerOrInterchange(TypedDict, total=False):
eager_or_interchange_only: Required[Literal[True]]
series_only: Literal[False]
allow_series: bool | None


class OnlyEagerOrInterchange(_OnlyEagerOrInterchange, total=False):
pass_through: bool | None


class OnlyEagerOrInterchangeStrict(_OnlyEagerOrInterchange, total=False):
strict: bool | None


class _AllowLazy(TypedDict, total=False):
eager_only: Literal[False]
series_only: Literal[False]
allow_series: bool | None


class AllowLazy(_AllowLazy, total=False):
pass_through: bool


class AllowLazyV1(_AllowLazy, total=False):
pass_through: bool | None
eager_or_interchange_only: Literal[False]


class AllowLazyStrictV1(_AllowLazy, total=False):
strict: bool | None
eager_or_interchange_only: Literal[False]


class _AllowAny(TypedDict, total=False):
eager_only: Literal[False]
series_only: Literal[False]
allow_series: Required[Literal[True]]


class AllowAny(_AllowAny, total=False):
pass_through: bool


class AllowAnyV1(_AllowAny, total=False):
pass_through: bool | None
eager_or_interchange_only: Literal[False]


class AllowAnyStrictV1(_AllowAny, total=False):
strict: bool | None
eager_or_interchange_only: Literal[False]


class _Unknown(TypedDict, total=False):
eager_only: bool
series_only: bool
allow_series: bool | None


class PassThroughUnknown(_Unknown, total=False):
pass_through: Required[Literal[True]]


class PassThroughUnknownV1(_Unknown, total=False):
pass_through: Required[Literal[True]]
eager_or_interchange_only: bool


class StrictUnknownV1(_Unknown, total=False):
strict: Required[Literal[False]]
eager_or_interchange_only: bool
Loading
Loading