22
33If you find yourself being yelled at by a typechecker and ended up here - **do not fear!**
44
5- ### (1) `Native(*Frame|Series)`
6- Minimal [`Protocol`]s for matching *almost any* supported native type of that group:
5+ We have 5 funky flavors, which tackle two different problem spaces.
6+
7+ How do we describe [Native types] when ...
8+ - ... **wrapping in** a [Narwhals type]?
9+ - ... **matching to** an [`Implementation`]?
10+
11+ ## Wrapping in a Narwhals type
12+ [//]: # (TODO @dangotbanned: Replace `Thing` with a better name)
13+
14+ The following examples use the placeholder type `Thing` which represents one of:
15+ - `DataFrame`: (Eager) 2D data structure representing data as a table with rows and columns.
16+ - `LazyFrame`: (Lazy) Computation graph/query against a DataFrame/database.
17+ - `Series`: 1D data structure representing a single column.
18+
19+ Our goal is to **wrap** a *partially-unknown* native object **in** a [generic class]:
20+
21+ DataFrame[IntoDataFrameT]
22+ LazyFrame[IntoLazyFrameT]
23+ Series[IntoSeriesT]
24+
25+ ### (1) `Native<Thing>`
26+ Minimal [`Protocol`]s that are [assignable to] *almost any* supported native type of that group:
727
828 class NativeThing(Protocol):
929 def something_common(self, *args: Any, **kwargs: Any) -> Any: ...
1030
1131Note:
1232 This group is primarily a building block for more useful types.
1333
14- ### (2) `Into(*Frame|Series) `
34+ ### (2) `Into<Thing> `
1535*Publicly* exported [`TypeAlias`]s of **(1)**:
1636
1737 IntoThing: TypeAlias = NativeThing
@@ -23,7 +43,7 @@ def something_common(self, *args: Any, **kwargs: Any) -> Any: ...
2343Tip:
2444 Reach for these when there **isn't a need to preserve** the original native type.
2545
26- ### (3) `Into(*Frame|Series) T`
46+ ### (3) `Into<Thing> T`
2747*Publicly* exported [`TypeVar`]s, bound to **(2)**:
2848
2949 IntoThingT = TypeVar("IntoThingT", bound=IntoThing)
@@ -36,14 +56,10 @@ def something_common(self, *args: Any, **kwargs: Any) -> Any: ...
3656 class Thing(Generic[IntoThingT]):
3757 def to_native(self) -> IntoThingT: ...
3858
39- ### (4) `Native<Backend>`
40- Everything so far has been focused on the idea of matching an *unknown* native object to
41- a [`Protocol`] used by a [generic class]:
42-
43- DataFrame[IntoDataFrameT]
44- LazyFrame[IntoLazyFrameT]
45- Series[IntoSeriesT]
59+ ## Matching to an `Implementation`
60+ [//]: # (TODO @dangotbanned: Introduce this section?)
4661
62+ ### (4) `Native<Backend>`
4763If we want to describe a set of more specific types (e.g. in [`@overload`s]), then these protocols/aliases are the right tool.
4864
4965For common and easily-installed backends, aliases are composed of the native type(s):
@@ -67,7 +83,11 @@ class NativeDask(NativeLazyFrame, Protocol):
6783
6884[structural]: https://typing.python.org/en/latest/spec/glossary.html#term-structural
6985[nominal]: https://typing.python.org/en/latest/spec/glossary.html#term-nominal
86+ [Native types]: https://narwhals-dev.github.io/narwhals/how_it_works/#polars-and-other-implementations
87+ [Narwhals type]: https://narwhals-dev.github.io/narwhals/api-reference/dataframe/
88+ [`Implementation`]: https://narwhals-dev.github.io/narwhals/api-reference/implementation/
7089[`Protocol`]: https://typing.python.org/en/latest/spec/protocol.html
90+ [assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable
7191[`TypeAlias`]: https://mypy.readthedocs.io/en/stable/kinds_of_types.html#type-aliases
7292[`TypeVar`]: https://mypy.readthedocs.io/en/stable/generics.html#type-variables-with-upper-bounds
7393[generic class]: https://docs.python.org/3/library/typing.html#user-defined-generic-types
0 commit comments