|
73 | 73 | NativeSeriesT_co, |
74 | 74 | ) |
75 | 75 | from narwhals._compliant.typing import EvalNames, NativeDataFrameT, NativeLazyFrameT |
76 | | - from narwhals._namespace import Namespace |
| 76 | + from narwhals._namespace import ( |
| 77 | + Namespace, |
| 78 | + _NativeArrow, |
| 79 | + _NativeCuDF, |
| 80 | + _NativeDask, |
| 81 | + _NativeDuckDB, |
| 82 | + _NativeIbis, |
| 83 | + _NativeModin, |
| 84 | + _NativePandas, |
| 85 | + _NativePandasLike, |
| 86 | + _NativePolars, |
| 87 | + _NativePySpark, |
| 88 | + _NativePySparkConnect, |
| 89 | + _NativeSQLFrame, |
| 90 | + ) |
77 | 91 | from narwhals._translate import ArrowStreamExportable, IntoArrowTable, ToNarwhalsT_co |
78 | 92 | from narwhals._typing import ( |
79 | 93 | Backend, |
80 | 94 | IntoBackend, |
| 95 | + _ArrowImpl, |
| 96 | + _CudfImpl, |
| 97 | + _DaskImpl, |
| 98 | + _DuckDBImpl, |
81 | 99 | _EagerAllowedImpl, |
| 100 | + _IbisImpl, |
82 | 101 | _LazyAllowedImpl, |
83 | 102 | _LazyFrameCollectImpl, |
| 103 | + _ModinImpl, |
| 104 | + _PandasImpl, |
| 105 | + _PandasLikeImpl, |
| 106 | + _PolarsImpl, |
| 107 | + _PySparkConnectImpl, |
| 108 | + _PySparkImpl, |
| 109 | + _SQLFrameImpl, |
84 | 110 | ) |
85 | 111 | from narwhals.dataframe import DataFrame, LazyFrame |
86 | 112 | from narwhals.dtypes import DType |
@@ -141,7 +167,7 @@ def columns(self) -> Sequence[str]: ... |
141 | 167 | _Constructor: TypeAlias = "Callable[Concatenate[_T, P], R2]" |
142 | 168 |
|
143 | 169 |
|
144 | | -class _StoresNative(Protocol[NativeT_co]): # noqa: PYI046 |
| 170 | +class _StoresNative(Protocol[NativeT_co]): |
145 | 171 | """Provides access to a native object. |
146 | 172 |
|
147 | 173 | Native objects have types like: |
@@ -2034,3 +2060,91 @@ def deep_attrgetter(attr: str, *nested: str) -> attrgetter[Any]: |
2034 | 2060 | def deep_getattr(obj: Any, name_1: str, *nested: str) -> Any: |
2035 | 2061 | """Perform a nested attribute lookup on `obj`.""" |
2036 | 2062 | return deep_attrgetter(name_1, *nested)(obj) |
| 2063 | + |
| 2064 | + |
| 2065 | +class Compliant( |
| 2066 | + _StoresNative[NativeT_co], _StoresImplementation, Protocol[NativeT_co] |
| 2067 | +): ... |
| 2068 | + |
| 2069 | + |
| 2070 | +class Narwhals(Protocol[NativeT_co]): |
| 2071 | + """Minimal *Narwhals-level* protocol. |
| 2072 | +
|
| 2073 | + Provides access to a compliant object: |
| 2074 | +
|
| 2075 | + obj: Narwhals[NativeT_co]] |
| 2076 | + compliant: Compliant[NativeT_co] = obj._compliant |
| 2077 | +
|
| 2078 | + Which itself exposes: |
| 2079 | +
|
| 2080 | + implementation: Implementation = compliant.implementation |
| 2081 | + native: NativeT_co = compliant.native |
| 2082 | +
|
| 2083 | + This interface is used for revealing which `Implementation` member is associated with **either**: |
| 2084 | + - One or more [nominal] native type(s) |
| 2085 | + - One or more [structural] type(s) |
| 2086 | + - where the true native type(s) are [assignable to] *at least* one of them |
| 2087 | +
|
| 2088 | + These relationships are defined in the `@overload`s of `_Implementation.__get__(...)`. |
| 2089 | +
|
| 2090 | + [nominal]: https://typing.python.org/en/latest/spec/glossary.html#term-nominal |
| 2091 | + [structural]: https://typing.python.org/en/latest/spec/glossary.html#term-structural |
| 2092 | + [assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable |
| 2093 | + """ |
| 2094 | + |
| 2095 | + @property |
| 2096 | + def _compliant(self) -> Compliant[NativeT_co]: ... |
| 2097 | + |
| 2098 | + |
| 2099 | +class _Implementation: |
| 2100 | + """Descriptor for matching an opaque `Implementation` on a generic class. |
| 2101 | +
|
| 2102 | + Based on [pyright comment](https://github.com/microsoft/pyright/issues/3071#issuecomment-1043978070) |
| 2103 | + """ |
| 2104 | + |
| 2105 | + def __set_name__(self, owner: type[Any], name: str) -> None: |
| 2106 | + self.__name__: str = name |
| 2107 | + |
| 2108 | + @overload |
| 2109 | + def __get__(self, instance: Narwhals[_NativePolars], owner: Any) -> _PolarsImpl: ... |
| 2110 | + @overload |
| 2111 | + def __get__(self, instance: Narwhals[_NativePandas], owner: Any) -> _PandasImpl: ... |
| 2112 | + @overload |
| 2113 | + def __get__(self, instance: Narwhals[_NativeModin], owner: Any) -> _ModinImpl: ... |
| 2114 | + @overload # TODO @dangotbanned: Rename `_typing` `*Cudf*` aliases to `*CuDF*` |
| 2115 | + def __get__(self, instance: Narwhals[_NativeCuDF], owner: Any) -> _CudfImpl: ... |
| 2116 | + @overload |
| 2117 | + def __get__( |
| 2118 | + self, instance: Narwhals[_NativePandasLike], owner: Any |
| 2119 | + ) -> _PandasLikeImpl: ... |
| 2120 | + @overload |
| 2121 | + def __get__(self, instance: Narwhals[_NativeArrow], owner: Any) -> _ArrowImpl: ... |
| 2122 | + @overload |
| 2123 | + def __get__( |
| 2124 | + self, instance: Narwhals[_NativePolars | _NativeArrow | _NativePandas], owner: Any |
| 2125 | + ) -> _PolarsImpl | _PandasImpl | _ArrowImpl: ... |
| 2126 | + @overload |
| 2127 | + def __get__(self, instance: Narwhals[_NativeDuckDB], owner: Any) -> _DuckDBImpl: ... |
| 2128 | + @overload |
| 2129 | + def __get__( |
| 2130 | + self, instance: Narwhals[_NativeSQLFrame], owner: Any |
| 2131 | + ) -> _SQLFrameImpl: ... |
| 2132 | + @overload |
| 2133 | + def __get__(self, instance: Narwhals[_NativeDask], owner: Any) -> _DaskImpl: ... |
| 2134 | + @overload |
| 2135 | + def __get__(self, instance: Narwhals[_NativeIbis], owner: Any) -> _IbisImpl: ... |
| 2136 | + @overload |
| 2137 | + def __get__( |
| 2138 | + self, instance: Narwhals[_NativePySpark | _NativePySparkConnect], owner: Any |
| 2139 | + ) -> _PySparkImpl | _PySparkConnectImpl: ... |
| 2140 | + # NOTE: https://docs.python.org/3/howto/descriptor.html#invocation-from-a-class |
| 2141 | + @overload |
| 2142 | + def __get__(self, instance: None, owner: type[Narwhals[Any]]) -> Self: ... |
| 2143 | + @overload |
| 2144 | + def __get__( |
| 2145 | + self, instance: DataFrame[Any] | Series[Any], owner: Any |
| 2146 | + ) -> _EagerAllowedImpl: ... |
| 2147 | + @overload |
| 2148 | + def __get__(self, instance: LazyFrame[Any], owner: Any) -> _LazyAllowedImpl: ... |
| 2149 | + def __get__(self, instance: Narwhals[Any] | None, owner: Any) -> Any: |
| 2150 | + return self if instance is None else instance._compliant._implementation |
0 commit comments