o
    $&]i*<                     @  s  U d Z ddlmZ ddlmZmZmZmZ ddlm	Z	m
Z
mZmZmZmZ ddlmZmZmZmZmZmZmZmZmZmZmZ e	rzddlZddlZddlZddl Z!ddl"m#Z$ ddl%m&Z&m'Z'm(Z( e$e
e
e
e
e
f Z)ed	Z*d
Z+de,d< e
Z-de,d< g dZ.G dd deZ/G dd dee/eZ0G dd de/eZ1G dd deee
 eZ2G dd deeZ3G dd de0e3eZ4G dd de2e3eZ5G dd de1eZ6G dd  d e4eZ7G d!d" d"e5eZ8G d#d$ d$e/eZ9G d%d& d&e4eZ:G d'd( d(e5eZ;G d)d* d*e1eZ<d+Z=de,d,< d-Z>de,d.< d/Z?de,d0< d1Z@de,d2< d3ZAde,d4< d5ZBde,d6< d7ZCde,d8< d9ZDde,d:< d;ZEde,d<< d=ZFde,d>< e<ZGde,d?< e<ZHde,d@< dAZIde,dB< dCZJde,dD< dEZKde,dF< dGZLde,dH< e0ZMde,dI< 	 ee1e9f ZNde,dJ< eeMeNf ZOde,dK< 	 e2ZPde,dL< 	 edMeOdNZQ	 edOeMdNZR	 edPeNdNZSedQePdNZT	 drdVdWZUdsdYdZZVed[eZWeZXd\e,d]< eZYd^e,d_< ed`eZZedaeZ[edbeZ\dtdddeZ]dudgdhZ^dvdjdkZ_dwdmdnZ`dxdpdqZadS )yu  The home for *mostly* [structural] counterparts to [nominal] native types.

If you find yourself being yelled at by a typechecker and ended up here - **do not fear!**

We have 5 funky flavors, which tackle two different problem spaces.

How do we describe [Native types] when ...
- ... **wrapping in** a [Narwhals type]?
- ... **matching to** an [`Implementation`]?

## Wrapping in a Narwhals type
[//]: # (TODO @dangotbanned: Replace `Thing` with a better name)

The following examples use the placeholder type `Thing` which represents one of:
- `DataFrame`: (Eager) 2D data structure representing data as a table with rows and columns.
- `LazyFrame`: (Lazy) Computation graph/query against a DataFrame/database.
- `Series`: 1D data structure representing a single column.

Our goal is to **wrap** a *partially-unknown* native object **in** a [generic class]:

    def wrapping_in_df(native: IntoDataFrameT) -> DataFrame[IntoDataFrameT]: ...
    def wrapping_in_lf(native: IntoLazyFrameT) -> LazyFrame[IntoLazyFrameT]: ...
    def wrapping_in_ser(native: IntoSeriesT) -> Series[IntoSeriesT]: ...

### (1) `Native<Thing>`
Minimal [`Protocol`]s that are [assignable to] *almost any* supported native type of that group:

    class NativeThing(Protocol):
        def something_common(self, *args: Any, **kwargs: Any) -> Any: ...

Note:
    This group is primarily a building block for more useful types.

### (2) `Into<Thing>`
*Publicly* exported [`TypeAlias`]s of **(1)**:

    IntoThing: TypeAlias = NativeThing

**But**, occasionally, there'll be an edge-case which we can spell like:

    IntoThing: TypeAlias = Union[<type that does not fit the protocol>, NativeThing]

Tip:
    Reach for these when there **isn't a need to preserve** the original native type.

### (3) `Into<Thing>T`
*Publicly* exported [`TypeVar`]s, bound to **(2)**:

    IntoThingT = TypeVar("IntoThingT", bound=IntoThing)

Important:
    In most situations, you'll want to use these as they **do preserve** the original native type.

Putting it all together, we can now add a *narwhals-level* wrapper:

    class Thing(Generic[IntoThingT]):
        def to_native(self) -> IntoThingT: ...

## Matching to an `Implementation`
This problem differs as we need to *create* a relationship between *otherwise-unrelated* types.

Comparing the problems side-by-side, we can more clearly see this difference:

    def wrapping_in_df(native: IntoDataFrameT) -> DataFrame[IntoDataFrameT]: ...
    def matching_to_polars(native: pl.DataFrame) -> Literal[Implementation.POLARS]: ...

### (4) `Native<Backend>`
If we want to describe a set of specific types and **match** them in [`@overload`s], then these the tools we need.

For common and easily-installed backends, [`TypeAlias`]s are composed of the native type(s):

    NativePolars: TypeAlias = pl.DataFrame | pl.LazyFrame | pl.Series

Otherwise, we need to define a [`Protocol`] which the native type(s) can **match** against *when* installed:

    class NativeDask(NativeLazyFrame, Protocol):
        _partition_type: type[pd.DataFrame]

Tip:
    The goal is to be as minimal as possible, while still being *specific-enough* to **not match** something else.

Important:
    See [ibis#9276 comment] for a more *in-depth* example that doesn't fit here 😄

### (5) `is_native_<backend>`
[Type guards] for **(4)**, *similar* to those found in `nw.dependencies`.

They differ by checking **all** native types/protocols in a single-call and using ``Native<Backend>`` aliases.

[structural]: https://typing.python.org/en/latest/spec/glossary.html#term-structural
[nominal]: https://typing.python.org/en/latest/spec/glossary.html#term-nominal
[Native types]: https://narwhals-dev.github.io/narwhals/how_it_works/#polars-and-other-implementations
[Narwhals type]: https://narwhals-dev.github.io/narwhals/api-reference/dataframe/
[`Implementation`]: https://narwhals-dev.github.io/narwhals/api-reference/implementation/
[`Protocol`]: https://typing.python.org/en/latest/spec/protocol.html
[assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable
[`TypeAlias`]: https://mypy.readthedocs.io/en/stable/kinds_of_types.html#type-aliases
[`TypeVar`]: https://mypy.readthedocs.io/en/stable/generics.html#type-variables-with-upper-bounds
[generic class]: https://docs.python.org/3/library/typing.html#user-defined-generic-types
[`@overload`s]: https://typing.python.org/en/latest/spec/overload.html
[ibis#9276 comment]: https://github.com/ibis-project/ibis/issues/9276#issuecomment-3292016818
[Type guards]: https://typing.python.org/en/latest/spec/narrowing.html
    )annotations)Callable
CollectionIterableSized)TYPE_CHECKINGAnyProtocolTypeVarUnioncast)get_cudf	get_modin
get_pandas
get_polarsget_pyarrowis_dask_dataframeis_duckdb_relationis_ibis_tableis_pyspark_connect_dataframeis_pyspark_dataframeis_sqlframe_dataframeN)BaseDataFrame)Self	TypeAliasTypeIsTzCallable[[Any], TypeIs[T]]r   _Guard
Incomplete)+IntoDataFrameIntoDataFrameT	IntoFrame
IntoFrameTIntoLazyFrameIntoLazyFrameT
IntoSeriesIntoSeriesT	NativeAnyNativeArrow
NativeCuDF
NativeDaskNativeDataFrameNativeDuckDBNativeFrame
NativeIbisNativeKnownNativeLazyFrameNativeModinNativePandasNativePandasLikeNativePandasLikeDataFrameNativePandasLikeSeriesNativePolarsNativePySparkNativePySparkConnectNativeSQLFrameNativeSeriesNativeSparkLikeNativeUnknownis_native_arrowis_native_cudfis_native_daskis_native_duckdbis_native_ibisis_native_modinis_native_pandasis_native_pandas_likeis_native_polarsis_native_pysparkis_native_pyspark_connectis_native_spark_likeis_native_sqlframec                   @  s$   e Zd Zed
ddZdddZd	S )r-   returnr   c                 C     d S N selfrM   rM   N/var/www/html/IGF-ODF-V3/venv/lib/python3.10/site-packages/narwhals/_native.pycolumns      zNativeFrame.columnsargskwargsc                 O  rK   rL   rM   rO   rS   rT   rM   rM   rP   join       zNativeFrame.joinNrJ   r   rS   r   rT   r   rJ   r   )__name__
__module____qualname__propertyrQ   rV   rM   rM   rM   rP   r-      s    r-   c                   @     e Zd ZdddZdS )	r+   rS   r   rT   rJ   c                 O  rK   rL   rM   rU   rM   rM   rP   drop   rW   zNativeDataFrame.dropNrY   )rZ   r[   r\   r_   rM   rM   rM   rP   r+          r+   c                   @  r^   )	r0   rS   r   rT   rJ   c                 O  rK   rL   rM   rU   rM   rM   rP   explain   rW   zNativeLazyFrame.explainNrY   )rZ   r[   r\   ra   rM   rM   rM   rP   r0      r`   r0   c                   @  s*   e Zd ZdddZdddZdd	d
ZdS )r:   rS   r   rT   rJ   c                 O  rK   rL   rM   rU   rM   rM   rP   filter   rW   zNativeSeries.filterc                 O  rK   rL   rM   rU   rM   rM   rP   value_counts   rW   zNativeSeries.value_countsc                 O  rK   rL   rM   rU   rM   rM   rP   unique   rW   zNativeSeries.uniqueNrY   )rZ   r[   r\   rb   rc   rd   rM   rM   rM   rP   r:      s    

r:   c                   @  sz   e Zd ZU ded< 	 d$ddZd%d
dZd%ddZed&ddZed'ddZ	dddd(ddZ
d)d*ddZd+d!d"Zd#S ),_BasePandasLiker   indexkeyrJ   c                C  rK   rL   rM   )rO   rg   rM   rM   rP   __getitem__   rW   z_BasePandasLike.__getitem__other float | Collection[float] | Selfr   c                C  rK   rL   rM   rO   ri   rM   rM   rP   __mul__   rW   z_BasePandasLike.__mul__c                C  rK   rL   rM   rk   rM   rM   rP   __floordiv__   rW   z_BasePandasLike.__floordiv__c                 C  rK   rL   rM   rN   rM   rM   rP   loc   rR   z_BasePandasLike.loctuple[int, ...]c                 C  rK   rL   rM   rN   rM   rM   rP   shape   rR   z_BasePandasLike.shape.)axiscopylabelsrq   rr   boolc                C  rK   rL   rM   )rO   rs   rq   rr   rM   rM   rP   set_axis   rW   z_BasePandasLike.set_axisdeepc                 C  rK   rL   rM   )rO   rv   rM   rM   rP   rr      rW   z_BasePandasLike.copyrS   kwdsSelf | Incompletec                 O  s   dS )z`mypy` & `pyright` disagree on overloads.

        `Incomplete` used to fix [more important issue](https://github.com/narwhals-dev/narwhals/pull/3016#discussion_r2296139744).
        NrM   rO   rS   rw   rM   rM   rP   rename   rW   z_BasePandasLike.renameN)rg   r   rJ   r   )ri   rj   rJ   r   rX   )rJ   ro   )rs   r   rq   r   rr   rt   rJ   r   .)rv   rt   rJ   r   )rS   r   rw   r   rJ   rx   )rZ   r[   r\   __annotations__rh   rl   rm   r]   rn   rp   ru   rr   rz   rM   rM   rM   rP   re      s   
 


re   c                   @  s   e Zd ZdS )_BasePandasLikeFrameN)rZ   r[   r\   rM   rM   rM   rP   r}      s    r}   c                   @  s6   e Zd ZU ded< 				ddddZddddZdS )_BasePandasLikeSeries
Any | NonenameNdataIterable[Any] | Nonerf   dtyperS   r   rT   rJ   Nonec                 O  rK   rL   rM   )rO   r   rf   r   r   rS   rT   rM   rM   rP   __init__   s   z_BasePandasLikeSeries.__init__.condri   rx   c                C  rK   rL   rM   )rO   r   ri   rM   rM   rP   where   rW   z_BasePandasLikeSeries.where)NNNN)r   r   rf   r   r   r   r   r   rS   r   rT   r   rJ   r   r{   )r   r   ri   r   rJ   rx   )rZ   r[   r\   r|   r   r   rM   rM   rM   rP   r~      s   
 	r~   c                   @     e Zd ZU ded< dS )r*   type[pd.DataFrame]_partition_typeNrZ   r[   r\   r|   rM   rM   rM   rP   r*         
 r*   c                   @  r^   )	_CuDFDataFramerS   r   rw   rJ   c                 O  rK   rL   rM   ry   rM   rM   rP   to_pylibcudf   rW   z_CuDFDataFrame.to_pylibcudfNrS   r   rw   r   rJ   r   rZ   r[   r\   r   rM   rM   rM   rP   r      r`   r   c                   @  r^   )	_CuDFSeriesrS   r   rw   rJ   c                 O  rK   rL   rM   ry   rM   rM   rP   r      rW   z_CuDFSeries.to_pylibcudfNr   r   rM   rM   rM   rP   r      r`   r   c                   @  s4   e Zd ZdddZdddZdd	d
ZdddZdS )r.   rS   r   rw   rJ   c                 O  rK   rL   rM   ry   rM   rM   rP   sql  rW   zNativeIbis.sqlc                 O  rK   rL   rM   ry   rM   rM   rP   __pyarrow_result__  rW   zNativeIbis.__pyarrow_result__c                 O  rK   rL   rM   ry   rM   rM   rP   __pandas_result__  rW   zNativeIbis.__pandas_result__c                 O  rK   rL   rM   ry   rM   rM   rP   __polars_result__  rW   zNativeIbis.__polars_result__Nr   )rZ   r[   r\   r   r   r   r   rM   rM   rM   rP   r.     s
    


r.   c                   @  r   )_ModinDataFramer   _pandas_classNr   rM   rM   rM   rP   r     r   r   c                   @  r   )_ModinSeriesztype[pd.Series[Any]]r   Nr   rM   rM   rM   rP   r     r   r   c                   @  r^   )	_PySparkDataFrameargr   rT   rJ   c                 O  rK   rL   rM   )rO   r   rT   rM   rM   rP   dropDuplicatesWithinWatermark  rW   z/_PySparkDataFrame.dropDuplicatesWithinWatermarkN)r   r   rT   r   rJ   r   )rZ   r[   r\   r   rM   rM   rM   rP   r     r`   r   z'pl.DataFrame | pl.LazyFrame | pl.Seriesr6   zpa.Table | pa.ChunkedArray[Any]r(   zduckdb.DuckDBPyRelationr,   zpd.DataFrame | pd.Series[Any]r2   z_ModinDataFrame | _ModinSeriesr1   z_CuDFDataFrame | _CuDFSeriesr)   z+pd.Series[Any] | _CuDFSeries | _ModinSeriesr5   z/pd.DataFrame | _CuDFDataFrame | _ModinDataFramer4   z2NativePandasLikeDataFrame | NativePandasLikeSeriesr3   z'_BaseDataFrame[Any, Any, Any, Any, Any]r9   r7   r8   z5NativeSQLFrame | NativePySpark | NativePySparkConnectr;   zhNativePolars | NativeArrow | NativePandasLike | NativeSparkLike | NativeDuckDB | NativeDask | NativeIbisr/   z0NativeDataFrame | NativeSeries | NativeLazyFramer<   zNativeKnown | NativeUnknownr'   r   r#   r!   r%   r"   )boundr    r$   r&   objr   rJ   TypeIs[NativePolars]c                 C  s$   t   }d uot| |j|j|jfS rL   )r   
isinstance	DataFrameSeries	LazyFrame)r   plrM   rM   rP   rE   |  s   rE   TypeIs[NativeArrow]c                 C      t   }d uot| |j|jfS rL   )r   r   TableChunkedArray)r   parM   rM   rP   r=        r=   z_Guard[NativeDask]z_Guard[NativeDuckDB]r@   z_Guard[NativeSQLFrame]rI   z_Guard[NativePySpark]z_Guard[NativePySparkConnect]z_Guard[NativeIbis]TypeIs[NativePandas]c                 C  r   rL   )r   r   r   r   )r   pdrM   rM   rP   rC     s    rC   TypeIs[NativeModin]c                 C  r   rL   )r   r   r   r   )r   mpdrM   rM   rP   rB     r   rB   TypeIs[NativeCuDF]c                 C  r   rL   )r   r   r   r   )r   cudfrM   rM   rP   r>     r   r>   TypeIs[NativePandasLike]c                 C     t | pt| pt| S rL   )rC   r>   rB   r   rM   rM   rP   rD     s   rD   TypeIs[NativeSparkLike]c                 C  r   rL   )rI   rF   rG   r   rM   rM   rP   rH     s
   rH   )r   r   rJ   r   )r   r   rJ   r   )r   r   rJ   r   )r   r   rJ   r   )r   r   rJ   r   )r   r   rJ   r   )r   r   rJ   r   )b__doc__
__future__r   collections.abcr   r   r   r   typingr   r   r	   r
   r   r   narwhals.dependenciesr   r   r   r   r   r   r   r   r   r   r   duckdbpandasr   polarsr   pyarrowr   sqlframe.base.dataframer   _BaseDataFrametyping_extensionsr   r   r   SQLFrameDataFramer   r   r|   r   __all__r-   r+   r0   r:   re   r}   r~   r*   r   r   r.   r   r   r   r6   r(   r,   r2   r1   r)   r5   r4   r3   r9   r7   r8   r;   r/   r<   r'   r   r#   r!   r%   r"   r    r$   r&   rE   r=   r?   r@   rI   rF   rG   rA   rC   rB   r>   rD   rH   rM   rM   rM   rP   <module>   s    h 42








