o
    $&]i                    @  s>  U d dl mZ d dlZd dlZd dlZd dlmZmZmZm	Z	m
Z
mZ d dlmZ d dlmZmZ d dlmZmZmZmZ d dlmZ d dlmZmZ d d	lmZ d d
lmZ d dl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, d dl-m.Z. d dl/m0Z0 d dl1m2Z2m3Z3 d dl4m5Z5m6Z6m7Z7m8Z8m9Z9m:Z:m;Z;m<Z<m=Z=m>Z>m?Z?m@Z@mAZAmBZBmCZCmDZDmEZEmFZFmGZG d dlHmIZImJZJmKZK e"rd dlmLZL d dlMmNZN d dlOZPd dlQZRd dlSZTd dlUmVZVmWZWmXZXmYZYmZZZm[Z[ d dl\m]Z]m^Z^m_Z_ d dl`maZa d dlbmcZcmdZdmeZemfZf d dlgmhZh d dlimjZjmkZkmlZlmmZmmnZnmoZompZpmqZqmrZrmsZsmtZtmuZu d dlvmwZwmxZxmyZy d dlzm{Z{m|Z|m}Z}m~Z~mZmZmZmZmZmZmZmZmZmZmZmZmZ d dlmZmZ d dlmZ d dlmZ d dlmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZmZ eZd ed!< e)d"e*ee# ee# ee# f d#Ze)d$Ze)d%Ze)d&Ze)d'd(d#ZeXd)Ze)d*Ze)d+Ze)d,ZG d-d. d.e(ZG d/d0 d0e(ZG d1d2 d2e(Ze)d3Ze)d4d5d6Ze)d7d5d6Zd8Zd ed9< e)d:ed#Zd;Zd ed<< d=Zd ed>< G d?d@ d@e(e ZG dAdB dBe(e ZG dCdD dDe(ZG dEdF dFe(ZG dGdH dHe(ZG dIdJ dJeee(ZG dKdL dLeee(ZG dMdN dNee(ZG dOdP dPeZG dQdR dRe.ZejdSejdTejdUejdVejdWejdWejdXejdYejdZejd[ejd\iZd]ed^< ejd_ejd`ejdaejdbiZdcedd< 	 ededfddkdlZeddodpZӐddtduZԐddwdxZՐdd{d|Z֐dddZאdddZe,dddZe,dddZe,dddZe,dddZe,dddZe,dddZe,dddZِdddZِdddZڐdddZېdddZ	ddddddZݐdddZe"r;eed5dZnd dlZejdkrLeed5dZndddZdddZdddÄZdddǄZddd΄Zddd҄Z	ӐdԐdddلZ	ӐdԐdddۄZdddZdddZdddZdddZdddZdddZdddZdddZdddZdddZdddZdddZdd	d
ZdddZddddddZdddZdd d!Zdd%d&Zdd'd(Zdd.d/Zdd8d9Zdd;d<Zdd>d?ZddAdBZ e ZdCedD< ddFdGZddJdKZddNdOZddRdSZddTdUZddVdWZddYdZZ	dd]d^Z
dd`daZddcddZddfdgZddidjZddodpZddudvZddxdyZdd{d|ZG d}d~ d~ZdddZG dd dZdddZdddZdddZddd ddZG dd de&e ZeddfdddZdddZG dd dee ee(e ZG dd de(e ZG dd dZdddZ dddZ!dddZ"G dd deZ#e#j$Z$e%dZ&dS (      )annotationsN)
Collection	ContainerIterableIteratorMappingSequence)timezone)Enumauto)cache	lru_cachepartialwraps)	find_spec)getattr_staticgetdoc)chain)
attrgetter)	token_hex)TYPE_CHECKINGAnyCallableFinalGenericLiteralProtocolTypeVarUnioncastoverload)
NoAutoEnum)issue_deprecation_warning)assert_never
deprecated)get_cudfget_dask_dataframe
get_duckdbget_ibis	get_modin
get_pandas
get_polarsget_pyarrowget_pyspark_connectget_pyspark_sqlget_sqlframeis_narwhals_seriesis_narwhals_series_boolis_narwhals_series_intis_numpy_array_1dis_numpy_array_1d_boolis_numpy_array_1d_intis_pandas_like_dataframeis_pandas_like_series)ColumnNotFoundErrorDuplicateErrorInvalidOperationError)Set)
ModuleType)ConcatenateLiteralString	ParamSpecSelf	TypeAliasTypeIs)CompliantExprTCompliantSeriesTNativeSeriesT_co)NamespaceAccessor)Accessor	EvalNamesNativeDataFrameTNativeLazyFrameT	Namespace)NativeArrow
NativeCuDF
NativeDaskNativeDuckDB
NativeIbisNativeModinNativePandasNativePandasLikeNativePolarsNativePySparkNativePySparkConnectNativeSQLFrame)ArrowStreamExportableIntoArrowTableToNarwhalsT_co)BackendIntoBackend
_ArrowImpl	_CuDFImpl	_DaskImpl_DuckDBImpl_EagerAllowedImpl	_IbisImpl_LazyAllowedImpl_LazyFrameCollectImpl
_ModinImpl_PandasImpl_PandasLikeImpl_PolarsImpl_PySparkConnectImpl_PySparkImpl_SQLFrameImpl	DataFrame	LazyFrameDTypeSeries)CompliantDataFrameCompliantLazyFrameCompliantSeriesDTypes
FileSourceIntoSeriesTMultiIndexSelectorSingleIndexSelectorSizedMultiBoolSelectorSizedMultiIndexSelectorSizeUnitSupportsNativeNamespaceTimeUnit_1DArray_SliceIndex
_SliceName
_SliceNonerA   UnknownBackendNameFrameOrSeriesT)bound_T1_T2_T3_FnzCallable[..., Any]PRR1R2c                   @     e Zd ZU ded< dS )_SupportsVersionstr__version__N__name__
__module____qualname____annotations__ r   r   M/var/www/html/IGF-ODF-V3/venv/lib/python3.10/site-packages/narwhals/_utils.pyr      s   
 r   c                   @  s   e Zd Zd	d
ddZdS )_SupportsGetNinstancer   owner
Any | Nonereturnc                C     d S Nr   selfr   r   r   r   r   __get__   s    z_SupportsGet.__get__r   )r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r      s    r   c                   @     e Zd ZedddZdS )_StoresColumnsr   Sequence[str]c                 C  r   r   r   r   r   r   r   columns      z_StoresColumns.columnsN)r   r   )r   r   r   propertyr   r   r   r   r   r          r   _T
NativeT_coT)	covariantCompliantT_coz._FullContext | NamespaceAccessor[_FullContext]_IntoContext_IntoContextTz*Callable[Concatenate[_IntoContextT, P], R]_Methodz Callable[Concatenate[_T, P], R2]_Constructorc                   @     e Zd ZdZedddZdS )_StoresNativezProvides access to a native object.

    Native objects have types like:

    >>> from pandas import Series
    >>> from pyarrow import Table
    r   r   c                 C     dS )zReturn the native object.Nr   r   r   r   r   native      z_StoresNative.nativeN)r   r   )r   r   r   __doc__r   r   r   r   r   r   r          r   c                   @  r   )_StoresCompliantzProvides access to a compliant object.

    Compliant objects have types like:

    >>> from narwhals._pandas_like.series import PandasLikeSeries
    >>> from narwhals._arrow.dataframe import ArrowDataFrame
    r   r   c                 C  r   )zReturn the compliant object.Nr   r   r   r   r   	compliant   r   z_StoresCompliant.compliantN)r   r   )r   r   r   r   r   r   r   r   r   r   r      r   r   c                   @  r   )_StoresBackendVersionr   tuple[int, ...]c                 C  r   )z#Version tuple for a native package.Nr   r   r   r   r   _backend_version   r   z&_StoresBackendVersion._backend_versionNr   r   )r   r   r   r   r   r   r   r   r   r      r   r   c                   @  r   )_StoresVersionVersion_versionNr   r   r   r   r   r         
 r   c                   @  r   )_StoresImplementationImplementation_implementationNr   r   r   r   r   r      r   r   c                   @     e Zd ZdZdS )_LimitedContextzEProvides 2 attributes.

    - `_implementation`
    - `_version`
    Nr   r   r   r   r   r   r   r   r          r   c                   @  r   )_FullContextzMProvides 2 attributes.

    - `_implementation`
    - `_backend_version`
    Nr   r   r   r   r   r      r   r   c                   @     e Zd ZdZdddZdS )ValidateBackendVersionz=Ensure the target `Implementation` is on a supported version.r   Nonec                 C  s   | j  }dS )zRaise if installed version below `nw._utils.MIN_VERSIONS`.

        **Only use this when moving between backends.**
        Otherwise, the validation will have taken place already.
        N)r   r   )r   _r   r   r   _validate_backend_version   s   z0ValidateBackendVersion._validate_backend_versionN)r   r   )r   r   r   r   r   r   r   r   r   r      s    r   c                   @  sd   e Zd Ze Ze Ze ZedddZedddZ	edd	d
Z
edddZedddZdS )r   r   type[Namespace[Any]]c                 C  D   | t ju rddlm} |S | t ju rddlm} |S ddlm} |S )Nr   rK   )r   V1narwhals.stable.v1._namespacerL   V2narwhals.stable.v2._namespacenarwhals._namespace)r   NamespaceV1NamespaceV2rL   r   r   r   	namespace      

zVersion.namespacerw   c                 C  r   )Nr   )dtypes)r   r   narwhals.stable.v1r   r   narwhals.stable.v2narwhals)r   	dtypes_v1	dtypes_v2r   r   r   r   r   
  r   zVersion.dtypestype[DataFrame[Any]]c                 C  r   )Nr   rn   )r   r   r   rn   r   r   narwhals.dataframe)r   DataFrameV1DataFrameV2rn   r   r   r   	dataframe  r   zVersion.dataframetype[LazyFrame[Any]]c                 C  r   )Nr   ro   )r   r   r   ro   r   r   r   )r   LazyFrameV1LazyFrameV2ro   r   r   r   	lazyframe&  r   zVersion.lazyframetype[Series[Any]]c                 C  r   )Nr   rr   )r   r   r   rs   r   r   narwhals.series)r   SeriesV1SeriesV2rs   r   r   r   series4  r   zVersion.seriesN)r   r   )r   rw   )r   r   )r   r   )r   r   )r   r   r   r   r   r   MAINr   r   r   r   r   r   r   r   r   r   r      s    r   c                   @  s"  e Zd ZdZdZ	 dZ	 dZ	 dZ	 dZ	 dZ		 dZ
	 d	Z	 d
Z	 dZ	 dZ	 dZ	 d@ddZedAddZedBddZedCddZdDdd ZdEd"d#ZdEd$d%ZdEd&d'ZdEd(d)ZdEd*d+ZdEd,d-ZdEd.d/ZdEd0d1ZdEd2d3ZdEd4d5ZdEd6d7Z dEd8d9Z!dEd:d;Z"dFd=d>Z#d?S )Gr   z?Implementation of native object (pandas, Polars, PyArrow, ...).pandasmodincudfpyarrowpysparkpolarsdaskduckdbibissqlframezpyspark[connect]unknownr   r   c                 C  s
   t | jS r   )r   valuer   r   r   r   __str___     
zImplementation.__str__cls
type[Self]native_namespacer<   c                 C  sj   t  tjt tjt tjt tjt	 tj
t tjt tjt tjt tjt tjt tji}||tjS )zInstantiate Implementation object from a native namespace module.

        Arguments:
            native_namespace: Native namespace.
        )r*   r   PANDASr)   MODINr%   CUDFr,   PYARROWr.   PYSPARKr+   POLARSr&   DASKr'   DUCKDBr(   IBISr/   SQLFRAMEr-   PYSPARK_CONNECTgetUNKNOWN)r  r  mappingr   r   r   from_native_namespaceb  s   
z$Implementation.from_native_namespacebackend_namec                 C  s$   z| |W S  t y   tj Y S w )zInstantiate Implementation object from a native namespace module.

        Arguments:
            backend_name: Name of backend, expressed as string.
        )
ValueErrorr   r  )r  r  r   r   r   from_stringz  s
   

zImplementation.from_stringbackend)IntoBackend[Backend] | UnknownBackendNamec                 C  s,   t |tr
| |S t |tr|S | |S )zInstantiate from native namespace module, string, or Implementation.

        Arguments:
            backend: Backend to instantiate Implementation from.
        )
isinstancer   r  r   r  )r  r  r   r   r   from_backend  s   
zImplementation.from_backendc                 C  s4   | t ju rd}t||   t| | j}t|S )zCReturn the native namespace module corresponding to Implementation.z:Cannot return native namespace from UNKNOWN Implementation)r   r  AssertionErrorr   _IMPLEMENTATION_TO_MODULE_NAMEr  r   _import_native_namespace)r   msgmodule_namer   r   r   to_native_namespace  s   
z"Implementation.to_native_namespaceboolc                 C  
   | t ju S )a7  Return whether implementation is pandas.

        Examples:
            >>> import pandas as pd
            >>> import narwhals as nw
            >>> df_native = pd.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_pandas()
            True
        )r   r  r   r   r   r   	is_pandas     
zImplementation.is_pandasc                 C     | t jt jt jhv S )aL  Return whether implementation is pandas, Modin, or cuDF.

        Examples:
            >>> import pandas as pd
            >>> import narwhals as nw
            >>> df_native = pd.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_pandas_like()
            True
        )r   r  r  r  r   r   r   r   is_pandas_like  s   zImplementation.is_pandas_likec                 C  r&  )aI  Return whether implementation is pyspark or sqlframe.

        Examples:
            >>> import pandas as pd
            >>> import narwhals as nw
            >>> df_native = pd.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_spark_like()
            False
        )r   r
  r  r  r   r   r   r   is_spark_like  s
   zImplementation.is_spark_likec                 C  r#  )a7  Return whether implementation is Polars.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_polars()
            True
        )r   r  r   r   r   r   	is_polars  r%  zImplementation.is_polarsc                 C  r#  )a4  Return whether implementation is cuDF.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_cudf()
            False
        )r   r  r   r   r   r   is_cudf  r%  zImplementation.is_cudfc                 C  r#  )a6  Return whether implementation is Modin.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_modin()
            False
        )r   r  r   r   r   r   is_modin  r%  zImplementation.is_modinc                 C  r#  )a:  Return whether implementation is PySpark.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_pyspark()
            False
        )r   r
  r   r   r   r   
is_pyspark  r%  zImplementation.is_pysparkc                 C  r#  )aB  Return whether implementation is PySpark.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_pyspark_connect()
            False
        )r   r  r   r   r   r   is_pyspark_connect   r%  z!Implementation.is_pyspark_connectc                 C  r#  )a:  Return whether implementation is PyArrow.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_pyarrow()
            False
        )r   r	  r   r   r   r   
is_pyarrow  r%  zImplementation.is_pyarrowc                 C  r#  )a4  Return whether implementation is Dask.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_dask()
            False
        )r   r  r   r   r   r   is_dask  r%  zImplementation.is_daskc                 C  r#  )a8  Return whether implementation is DuckDB.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_duckdb()
            False
        )r   r  r   r   r   r   	is_duckdb'  r%  zImplementation.is_duckdbc                 C  r#  )a4  Return whether implementation is Ibis.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_ibis()
            False
        )r   r  r   r   r   r   is_ibis4  r%  zImplementation.is_ibisc                 C  r#  )a<  Return whether implementation is SQLFrame.

        Examples:
            >>> import polars as pl
            >>> import narwhals as nw
            >>> df_native = pl.DataFrame({"a": [1, 2, 3]})
            >>> df = nw.from_native(df_native)
            >>> df.implementation.is_sqlframe()
            False
        )r   r  r   r   r   r   is_sqlframeA  r%  zImplementation.is_sqlframer   c                 C  s   t | S )zReturns backend version.backend_versionr   r   r   r   r   N  s   zImplementation._backend_versionNr   r   )r  r  r  r<   r   r   )r  r  r  r   r   r   )r  r  r  r  r   r   )r   r<   )r   r"  r   )$r   r   r   r   r  r  r  r	  r
  r  r  r  r  r  r  r  r  classmethodr  r  r  r!  r$  r'  r(  r)  r*  r+  r,  r-  r.  r/  r0  r1  r2  r   r   r   r   r   r   C  s`    















r   )   r7     )r         )   
   )   )r8     )r         )i  r9  )r7  r7  )   )r8     r   z(Mapping[Implementation, tuple[int, ...]]MIN_VERSIONSzdask.dataframezmodin.pandaszpyspark.sqlzpyspark.sql.connectzMapping[Implementation, str]r     )maxsizer   r   r   r<   c                 C  s   ddl m} || S )Nr   )import_module)	importlibrF  )r   rF  r   r   r   r  j  s   r  implementationr   c                C  s   t | ts	t|  | tju rdS | }t||j}t|}| r)dd l	}|j
}n| s1| r8dd l}|}n| rCdd l}|}n|}t|}|t|  }	k r`d| d|	 d| }
t|
|S )N)r   r   r   r   zMinimum version of z supported by Narwhals is z	, found: )r  r   r#   r  r  r  r   r  r2  sqlframe._versionr   r,  r-  r   r/  r   parse_versionrC  r  )rH  implr   r  r   into_versionr   r   versionmin_versionr  r   r   r   r4  t  s,   

r4  argsr   	list[Any]c                 C  s*   t t| dkrt| d r| d S | S )Nr7  r   )listlen_is_iterable)rO  r   r   r   flatten  s   *rT  argc                 C  s   t | ttfs
| fS | S r   )r  rQ  tuple)rU  r   r   r   tupleify  s   rW  Any | Iterable[Any]r"  c                 C  s   ddl m} t  }d urt| |j|jfs*t  }d ur6t| |j|j|j|jfr6dt| d}t	|t| t
oCt| tt|f S )Nr   rr   z(Expected Narwhals class or scalar, got: z`.

Hint: Perhaps you
- forgot a `nw.from_native` somewhere?
- used `pl.col` instead of `nw.col`?)r   rs   r*   r  rn   r+   Exprro   qualified_type_name	TypeErrorr   r   bytes)rU  rs   pdplr  r   r   r   rS    s    rS  valIterable[_T] | AnyTypeIs[Iterator[_T]]c                 C  
   t | tS r   )r  r   )r_  r   r   r   is_iterator  r  rc  rM  #str | ModuleType | _SupportsVersionc                 C  s:   t | tr| n| j}tdd|}tdd |dD S )zSimple version parser; split into a tuple of ints for comparison.

    Arguments:
        version: Version string, or object with one, to parse.
    z(\D?dev.*$) c                 s  s"    | ]}t td d|V  qdS )z\Dre  N)intresub).0vr   r   r   	<genexpr>  s     z parse_version.<locals>.<genexpr>.)r  r   r   rg  rh  rV  split)rM  version_strr   r   r   rJ    s   	rJ  
obj_or_clstypecls_or_tupletype[_T]TypeIs[type[_T]]c                 C  r   r   r   ro  rq  r   r   r   isinstance_or_issubclass  r   ru  object | typeTypeIs[_T | type[_T]]c                 C  r   r   r   rt  r   r   r   ru    r   tuple[type[_T1], type[_T2]]TypeIs[type[_T1 | _T2]]c                 C  r   r   r   rt  r   r   r   ru    r   #TypeIs[_T1 | _T2 | type[_T1 | _T2]]c                 C  r   r   r   rt  r   r   r   ru    r   &tuple[type[_T1], type[_T2], type[_T3]]TypeIs[type[_T1 | _T2 | _T3]]c                 C  r   r   r   rt  r   r   r   ru    r   /TypeIs[_T1 | _T2 | _T3 | type[_T1 | _T2 | _T3]]c                 C  r   r   r   rt  r   r   r   ru    r   tuple[type, ...]TypeIs[Any]c                 C  r   r   r   rt  r   r   r   ru    r   c                 C  s>   ddl m} t| |rt| |S t| |pt| tot| |S )Nr   rp   )narwhals.dtypesrq   r  rp  
issubclass)ro  rq  rq   r   r   r   ru    s   


itemsIterable[Any]r   c                   s\   ddl m m t fdd| D stfdd| D r d S ddd | D  }t|)	Nr   rm   c                 3      | ]}t | V  qd S r   r  ri  itemr   r   r   rk        z$validate_laziness.<locals>.<genexpr>c                 3  r  r   r  r  r   r   r   rk    r  zGThe items to concatenate should either all be eager, or all lazy, got: c                 S  s   g | ]}t |qS r   )rp  r  r   r   r   
<listcomp>  s    z%validate_laziness.<locals>.<listcomp>)r   rn   ro   allr[  )r  r  r   rm   r   validate_laziness  s   r  lhsrhs-Series[Any] | DataFrame[Any] | LazyFrame[Any]c                 C  s  ddl m} ddlm} ddd	}td| }td|}tt|d
d|rLtt|d
d|rL||jjj	 ||jjj	 |
|j|jjj|jjj	 S tt|d
d|r}tt|dd|r}||jjj	 ||jjj	 |
|j|jjj|jjj	 S tt|dd|rtt|d
d|r||jjj	 ||jjj	 |
|j|jjj|jjj	 S tt|dd|rtt|dd|r||jjj	 ||jjj	 |
|j|jjj|jjj	 S t|t|krdt| dt| }t|| S )a  Align `lhs` to the Index of `rhs`, if they're both pandas-like.

    Arguments:
        lhs: Dataframe or Series.
        rhs: Dataframe or Series to align with.

    Notes:
        This is only really intended for backwards-compatibility purposes,
        for example if your library already aligns indices for users.
        If you're designing a new library, we highly encourage you to not
        rely on the Index.
        For non-pandas-like inputs, this only checks that `lhs` and `rhs`
        are the same length.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import narwhals as nw
        >>> df_pd = pd.DataFrame({"a": [1, 2]}, index=[3, 4])
        >>> s_pd = pd.Series([6, 7], index=[4, 3])
        >>> df = nw.from_native(df_pd)
        >>> s = nw.from_native(s_pd, series_only=True)
        >>> nw.to_native(nw.maybe_align_index(df, s))
           a
        4  2
        3  1
    r   )PandasLikeDataFrame)PandasLikeSeriesindexr   r   r   c                 S  s   | j s	d}t|d S )Nz'given index doesn't have a unique index)	is_uniquer  )r  r  r   r   r   _validate_index$  s   z*maybe_align_index.<locals>._validate_index_compliant_frameN_compliant_seriesz6Expected `lhs` and `rhs` to have the same length, got z and )r  r   r   r   )narwhals._pandas_like.dataframer  narwhals._pandas_like.seriesr  r   r  getattrr  r   r  _with_compliant_with_nativelocr  rR  r  )r  r  r  r  r  lhs_anyrhs_anyr  r   r   r   maybe_align_index  s~   


r  obj-DataFrame[Any] | LazyFrame[Any] | Series[Any]r   c                 C  s,   t d| }| }t|st|r|jS dS )a  Get the index of a DataFrame or a Series, if it's pandas-like.

    Arguments:
        obj: Dataframe or Series.

    Notes:
        This is only really intended for backwards-compatibility purposes,
        for example if your library already aligns indices for users.
        If you're designing a new library, we highly encourage you to not
        rely on the Index.
        For non-pandas-like inputs, this returns `None`.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import narwhals as nw
        >>> df_pd = pd.DataFrame({"a": [1, 2], "b": [4, 5]})
        >>> df = nw.from_native(df_pd)
        >>> nw.maybe_get_index(df)
        RangeIndex(start=0, stop=2, step=1)
        >>> series_pd = pd.Series([1, 2])
        >>> series = nw.from_native(series_pd, series_only=True)
        >>> nw.maybe_get_index(series)
        RangeIndex(start=0, stop=2, step=1)
    r   N)r   	to_nativer6   r7   r  )r  obj_any
native_objr   r   r   maybe_get_index_  s
   
r  )r  column_namesstr | list[str] | Noner  6Series[IntoSeriesT] | list[Series[IntoSeriesT]] | Nonec                  s   ddl m  td| }| }|dur|durd}t||s)|du r)d}t||durAt|r: fdd|D n |d	d
}n|}t|rS||j|	|S t
|rwddlm	} |red}t||||| jjd}||j|S |S )a  Set the index of a DataFrame or a Series, if it's pandas-like.

    Arguments:
        obj: object for which maybe set the index (can be either a Narwhals `DataFrame`
            or `Series`).
        column_names: name or list of names of the columns to set as index.
            For dataframes, only one of `column_names` and `index` can be specified but
            not both. If `column_names` is passed and `df` is a Series, then a
            `ValueError` is raised.
        index: series or list of series to set as index.

    Raises:
        ValueError: If one of the following conditions happens

            - none of `column_names` and `index` are provided
            - both `column_names` and `index` are provided
            - `column_names` is provided and `df` is a Series

    Notes:
        This is only really intended for backwards-compatibility purposes, for example if
        your library already aligns indices for users.
        If you're designing a new library, we highly encourage you to not
        rely on the Index.

        For non-pandas-like inputs, this is a no-op.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import narwhals as nw
        >>> df_pd = pd.DataFrame({"a": [1, 2], "b": [4, 5]})
        >>> df = nw.from_native(df_pd)
        >>> nw.to_native(nw.maybe_set_index(df, "b"))  # doctest: +NORMALIZE_WHITESPACE
           a
        b
        4  1
        5  2
    r   r  r   Nz8Only one of `column_names` or `index` should be providedz3Either `column_names` or `index` should be providedc                   s   g | ]} |d dqS )Tpass_throughr   )ri  idxr  r   r   r        z#maybe_set_index.<locals>.<listcomp>Tr  )	set_indexz/Cannot set index using column names on a Series)rH  )narwhals.translater  r   r  rS  r6   r  r  r  r  r7   narwhals._pandas_like.utilsr  r   )r  r  r  df_anyr  r  keysr  r   r  r   maybe_set_index  s>   ,

r  c                 C  s   t d| }| }t|r%| }t||r|S ||j|jddS t	|rA| }t||r4|S ||j
|jddS |S )a  Reset the index to the default integer index of a DataFrame or a Series, if it's pandas-like.

    Arguments:
        obj: Dataframe or Series.

    Notes:
        This is only really intended for backwards-compatibility purposes,
        for example if your library already resets the index for users.
        If you're designing a new library, we highly encourage you to not
        rely on the Index.
        For non-pandas-like inputs, this is a no-op.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import narwhals as nw
        >>> df_pd = pd.DataFrame({"a": [1, 2], "b": [4, 5]}, index=([6, 7]))
        >>> df = nw.from_native(df_pd)
        >>> nw.to_native(nw.maybe_reset_index(df))
           a  b
        0  1  4
        1  2  5
        >>> series_pd = pd.Series([1, 2])
        >>> series = nw.from_native(series_pd, series_only=True)
        >>> nw.maybe_get_index(series)
        RangeIndex(start=0, stop=2, step=1)
    r   T)drop)r   r  r6   __native_namespace___has_default_indexr  r  r  reset_indexr7   r  )r  r  r  r  r   r   r   maybe_reset_index  s"   


r  )strict)r8  r<  	iterablesIterable[tuple[Any, ...]]c                    st   t | dk r
t|  S d d	 fdd}d	 fdd}t| }tt|| }ttt|tt|gR  | S )
Nr:  Fr   r   c                   3  s
    d d S )NTr   r   )first_stoppedr   r   
first_tail  s   zzip_strict.<locals>.first_tailc                  3  s0     s	d} t | tD ]}d} t | d S )Nz$zip_strict: first iterable is longerz%zip_strict: first iterable is shorter)r  r   from_iterable)r  r   r  restr   r   zip_tail  s   zzip_strict.<locals>.zip_tail)r   r   )rR  zipiterr   nextrQ  map)r  r  r  iterables_itfirstr   r  r   
zip_strict  s   
r  r  TypeIs[pd.RangeIndex]c                 C  s   t | |jS r   )r  
RangeIndex)r  r  r   r   r   _is_range_index-  s   r  native_frame_or_seriespd.Series[Any] | pd.DataFramec                 C  s2   | j }t||o|jdko|jt|ko|jdkS )Nr   r7  )r  r  startstoprR  step)r  r  r  r   r   r   r  1  s   
r  kwargs
bool | strc                 O  s:   | j  s| S | | j|  j|i |}td|S )a-  Convert columns or series to the best possible dtypes using dtypes supporting ``pd.NA``, if df is pandas-like.

    Arguments:
        obj: DataFrame or Series.
        *args: Additional arguments which gets passed through.
        **kwargs: Additional arguments which gets passed through.

    Notes:
        For non-pandas-like inputs, this is a no-op.
        Also, `args` and `kwargs` just get passed down to the underlying library as-is.

    Examples:
        >>> import pandas as pd
        >>> import polars as pl
        >>> import narwhals as nw
        >>> import numpy as np
        >>> df_pd = pd.DataFrame(
        ...     {
        ...         "a": pd.Series([1, 2, 3], dtype=np.dtype("int32")),
        ...         "b": pd.Series([True, False, np.nan], dtype=np.dtype("O")),
        ...     }
        ... )
        >>> df = nw.from_native(df_pd)
        >>> nw.to_native(
        ...     nw.maybe_convert_dtypes(df)
        ... ).dtypes  # doctest: +NORMALIZE_WHITESPACE
        a             Int32
        b           boolean
        dtype: object
    r   )rH  r'  r  
_compliantr  r  convert_dtypesr   )r  rO  r  resultr   r   r   maybe_convert_dtypes=  s   
!
r  szrf  unitr~   int | floatc                 C  s^   |dv r| S |dv r| d S |dv r| d S |dv r| d S |dv r&| d	 S d
|}t |)zScale size in bytes to other size units (eg: "kb", "mb", "gb", "tb").

    Arguments:
        sz: original size in bytes
        unit: size unit to convert into
    >   br\  >   kb	kilobytesi   >   mb	megabytesi   >   gb	gigabytesi   @>   tb	terabytesl        z9`unit` must be one of {'b', 'kb', 'mb', 'gb', 'tb'}, got r  )r  r  r  r   r   r   scale_bytesf  s   
r  r   Series[Any]c                 C  s   ddl m} | jjj}| j}d}t||r$t| j|jr$|jj	d }|S | j|j
kr.d}|S | j|jkr8d}|S |  }| j}| rT| dk rTtd|jjdk}|S | r`t|jj}|S | rsdd	lm} ||jor|jj}|S )
a  Return whether indices of categories are semantically meaningful.

    This is a convenience function to accessing what would otherwise be
    the `is_ordered` property from the DataFrame Interchange Protocol,
    see https://data-apis.org/dataframe-protocol/latest/API.html.

    - For Polars:
      - Enums are always ordered.
      - Categoricals are ordered if `dtype.ordering == "physical"`.
    - For pandas-like APIs:
      - Categoricals are ordered if `dtype.cat.ordered == True`.
    - For PyArrow table:
      - Categoricals are ordered if `dtype.type.ordered == True`.

    Arguments:
        series: Input Series.

    Examples:
        >>> import narwhals as nw
        >>> import pandas as pd
        >>> import polars as pl
        >>> data = ["x", "y"]
        >>>
        >>> s_pd = nw.from_native(
        ...     pd.Series(data, dtype=pd.CategoricalDtype(ordered=True)), series_only=True
        ... )
        >>> nw.is_ordered_categorical(s_pd)
        True
        >>> s_pl = nw.from_native(
        ...     pl.Series(data, dtype=pl.Categorical()), series_only=True
        ... )
        >>> nw.is_ordered_categorical(s_pl)
        False
    r   )InterchangeSeriesF
is_orderedT)r7      zpl.Categoricalphysical)is_dictionary)narwhals._interchange.seriesr  r  r   r   r  dtypeCategoricalr   describe_categoricalr
   r  rH  r)  r   r   orderingr'  r"  catorderedr.  narwhals._arrow.utilsr  rp  )r   r  r   r   r  r   rK  r  r   r   r   is_ordered_categorical{  s6   #
r  nwn_bytesr   Container[str]prefixc                 C  s   d}t |dd t| ||dS )Nz}Use `generate_temporary_column_name` instead. `generate_unique_token` is deprecated and it will be removed in future versionsz1.13.0r   )r  r   r  )r"   generate_temporary_column_name)r  r   r  r  r   r   r   generate_unique_token  s   r  c                 C  sP   d}	 | t | d  }||vr|S |d7 }|dkr'd| d| }t|q)a  Generates a unique column name that is not present in the given list of columns.

    It relies on [python secrets token_hex](https://docs.python.org/3/library/secrets.html#secrets.token_hex)
    function to return a string nbytes random bytes.

    Arguments:
        n_bytes: The number of bytes to generate for the token.
        columns: The list of columns to check for uniqueness.
        prefix: prefix with which the temporary column name should start with.

    Returns:
        A unique token that is not present in the given list of columns.

    Raises:
        AssertionError: If a unique token cannot be generated after 100 attempts.

    Examples:
        >>> import narwhals as nw
        >>> columns = ["abc", "xyz"]
        >>> nw.generate_temporary_column_name(n_bytes=8, columns=columns) not in columns
        True
        >>> temp_name = nw.generate_temporary_column_name(
        ...     n_bytes=8, columns=columns, prefix="foo"
        ... )
        >>> temp_name not in columns and temp_name.startswith("foo")
        True
    r   Tr7  d   zMInternal Error: Narwhals was not able to generate a column name with n_bytes=z and not in )r   r  )r  r   r  countertokenr  r   r   r   r    s   r  framesubsetIterable[str]r  	list[str]c               C  s:   |st t| j|S t |}t|| jd }r||S )N)	available)rQ  setr   intersectioncheck_columns_exist)r  r  r  to_droperrorr   r   r   parse_columns_to_drop  s   r  sequenceSequence[_T] | AnyTypeIs[Sequence[_T]]c                 C  s   t | to
t | t S r   )r  r   r   )r  r   r   r   is_sequence_but_not_str      r  TypeIs[_SliceNone]c                 C  s   t | to
| td kS r   )r  slicer  r   r   r   is_slice_none  r  r  CTypeIs[SizedMultiIndexSelector[Series[Any] | CompliantSeries[Any]]]c                 C  sD   t | ot| dkrt| d pt| dkp!t| p!t| p!t| S Nr   )r  rR  is_single_index_selectorr5   r2   is_compliant_series_intr  r   r   r   is_sized_multi_index_selector  s   "r  -TypeIs[Sequence[_T] | Series[Any] | _1DArray]c                 C  s    t | pt| pt| pt| S r   )r  r3   r0   is_compliant_seriesr  r   r   r   is_sequence_like  s   r  TypeIs[_SliceIndex]c                 C  sF   t | to"t | jtp"t | jtp"t | jttfo"| jd u o"| jd u S r   )r  r  r  rf  r  r  NoneTyper  r   r   r   is_slice_index!  s   

r  TypeIs[range]c                 C  rb  r   )r  ranger  r   r   r   is_range-  r  r  TypeIs[SingleIndexSelector]c                 C  s   t t| tot| t  S r   )r"  r  rf  r  r   r   r   r  1  s   r  TTypeIs[SingleIndexSelector | MultiIndexSelector[Series[Any] | CompliantSeries[Any]]]c                 C  s   t | pt| pt| S r   )r  r  r  r  r   r   r   is_index_selector5  s
   r!  BTypeIs[SizedMultiBoolSelector[Series[Any] | CompliantSeries[Any]]]c                 C  s:   t | rt| dkrt| d tpt| pt| pt| S r  )r  rR  r  r"  r4   r1   is_compliant_series_boolr  r   r   r   is_boolean_selector?  s   "r$  tpTypeIs[list[_T]]c                 C  s    t t| to| ot| d |S r  )r"  r  rQ  )r  r%  r   r   r   
is_list_ofJ  s    r'  
predicatesCollection[Any]TypeIs[Collection[list[bool]]]c                 C  s   t dd | D S )Nc                 s  s    | ]}t |tV  qd S r   )r'  r"  )ri  predr   r   r   rk  R  r  z3predicates_contains_list_of_bool.<locals>.<genexpr>any)r(  r   r   r    predicates_contains_list_of_boolO     r.  c                 C  s(   t t| ott| d  }ot||S r   )r"  r  r  r  r  )r  r%  r  r   r   r   is_sequence_ofU  s   r0  bool | Noner  pass_through_defaultc                C  sT   | d u r|d u r|}|S | d ur|d u r|  }|S | d u r$|d ur$	 |S d}t |)Nz,Cannot pass both `strict` and `pass_through`r  )r  r  r2  r  r   r   r   validate_strict_and_pass_though^  s   r3  re  F)warn_versionrequiredr4  r5  *Callable[[Callable[P, R]], Callable[P, R]]c                   s   d fdd}|S )a8  Decorator to transition from `native_namespace` to `backend` argument.

    Arguments:
        warn_version: Emit a deprecation warning from this version.
        required: Raise when both `native_namespace`, `backend` are `None`.

    Returns:
        Wrapped function, with `native_namespace` **removed**.
    fnCallable[P, R]r   c                  s   t  d	 fdd}|S )
NrO  P.argskwdsP.kwargsr   r   c                    s   | dd }| dd }|d ur!|d u r!rd}t|d |}n#|d ur/|d ur/d}t||d u rD|d u rDrDd j d}t|||d<  | i |S )Nr  r  z`native_namespace` is deprecated, please use `backend` instead.

Note: `native_namespace` will remain available in `narwhals.stable.v1`.
See https://narwhals-dev.github.io/narwhals/backcompat/ for more information.
r  z0Can't pass both `native_namespace` and `backend`z `backend` must be specified in `z`.)popr"   r  r   )rO  r:  r  r  r  )r7  r5  r4  r   r   wrapper~  s    z=deprecate_native_namespace.<locals>.decorate.<locals>.wrapper)rO  r9  r:  r;  r   r   )r   )r7  r=  r5  r4  r7  r   decorate}  s   z,deprecate_native_namespace.<locals>.decorateN)r7  r8  r   r8  r   )r4  r5  r@  r   r>  r   deprecate_native_namespacep  s   rA  window_sizemin_samples
int | Nonetuple[int, int]c                 C  sz   t | tdd t |ttd dd | dk rd}t||d ur7|dk r)d}t||| kr3d}t|| |fS | }| |fS )NrB  
param_namerC  r7  z+window_size must be greater or equal than 1z+min_samples must be greater or equal than 1z6`min_samples` must be less or equal than `window_size`)ensure_typerf  rp  r  r:   )rB  rC  r  r   r   r   _validate_rolling_arguments  s   rI  headernative_reprc              	   C  s  zt  j}W n ty   tt dd}Y nw |  }tdd |D }|d |krt|t	| }dd|  d}|t	|  }|d	d
|d   |  d
|d |d    d7 }|d	d|  d7 }|| d }|| d || d  }	|D ]}
|d	d
|  |
 d
|	| t	|
   d7 }qy|dd|  d7 }|S dt	|  }dd dd
|d   |  d
|d |d    dd d	S )NCOLUMNSP   c                 s      | ]}t |V  qd S r   )rR  )ri  liner   r   r   rk        z generate_repr.<locals>.<genexpr>r:  u   ┌u   ─u   ┐
| z|
-u   └u   ┘'   uu   ───────────────────────────────────────u   ┐
|u/   |
| Use `.to_native` to see native output |
└)
osget_terminal_sizer   OSErrorrf  getenv
expandtabs
splitlinesmaxrR  )rJ  rK  terminal_widthnative_linesmax_native_widthlengthoutputheader_extrastart_extra	end_extrarO  diffr   r   r   generate_repr  s<   0.
re  Collection[str]r  ColumnNotFoundError | Nonec               C  s"   t | | }rt||S d S r   )r  
differencer8   'from_missing_and_available_column_names)r  r  missingr   r   r   r    s
   r  c                 C  sh   t | t t| kr2ddlm} || }dd | D }ddd | D }d| }t|d S )	Nr   )Counterc                 S  s   i | ]\}}|d kr||qS )r7  r   ri  krj  r   r   r   
<dictcomp>  s    z1check_column_names_are_unique.<locals>.<dictcomp>re  c                 s  s&    | ]\}}d | d| dV  qdS )z
- 'z' z timesNr   rl  r   r   r   rk    s   $ z0check_column_names_are_unique.<locals>.<genexpr>z"Expected unique column names, got:)rR  r  collectionsrk  r  joinr9   )r   rk  r  
duplicatesr  r   r   r   check_column_names_are_unique  s   
rr  	time_unit$TimeUnit | Iterable[TimeUnit] | None	time_zone7str | timezone | Iterable[str | timezone | None] | None%tuple[Set[TimeUnit], Set[str | None]]c                 C  sd   | d u rh dnt | tr| hnt| }|d u rd hnt |ttfr't|hndd |D }||fS )N>   smsnsusc                 S  s    h | ]}|d urt |nd qS r   )r   )ri  tzr   r   r   	<setcomp>  s     z1_parse_time_unit_and_time_zone.<locals>.<setcomp>)r  r   r  r	   )rs  ru  
time_units
time_zonesr   r   r   _parse_time_unit_and_time_zone  s   	r  r  rq   r   rw   r~  Set[TimeUnit]r  Set[str | None]c                 C  s2   t | |jo| j|v o| j|v pd|v o| jd uS )N*)r  Datetimers  ru  )r  r   r~  r  r   r   r   %dtype_matches_time_unit_and_time_zone  s   
r  r   c                C  s   | j S r   r   )r  r   r   r   get_column_names  s   r  namesc                   s    fdd| j D S )Nc                   s   g | ]}| vr|qS r   r   )ri  col_namer  r   r   r    r  z(exclude_column_names.<locals>.<listcomp>r  )r  r  r   r  r   exclude_column_names
     r  EvalNames[Any]c                  s   d fdd}|S )N_framer   r   r   c                  s    S r   r   )r  r  r   r   r7    r   z$passthrough_column_names.<locals>.fn)r  r   r   r   r   )r  r7  r   r  r   passthrough_column_names  s   r  r   	_SENTINELattrc                 C  s   t | |ttuS r   )r   r  )r  r  r   r   r   _hasattr_static  s   r  \CompliantDataFrame[CompliantSeriesT, CompliantExprT, NativeDataFrameT, ToNarwhalsT_co] | Any^TypeIs[CompliantDataFrame[CompliantSeriesT, CompliantExprT, NativeDataFrameT, ToNarwhalsT_co]]c                 C  
   t | dS )N__narwhals_dataframe__r  r  r   r   r   is_compliant_dataframe  s   
r  JCompliantLazyFrame[CompliantExprT, NativeLazyFrameT, ToNarwhalsT_co] | AnyLTypeIs[CompliantLazyFrame[CompliantExprT, NativeLazyFrameT, ToNarwhalsT_co]]c                 C  r  )N__narwhals_lazyframe__r  r  r   r   r   is_compliant_lazyframe'     
r  'CompliantSeries[NativeSeriesT_co] | Any)TypeIs[CompliantSeries[NativeSeriesT_co]]c                 C  r  )N__narwhals_series__r  r  r   r   r   r  -  r  r  c                 C     t | o| j S r   )r  r  
is_integerr  r   r   r   r  3  r/  r  c                 C  r  r   )r  r  
is_booleanr  r   r   r   r#  9  r/  r#  'TypeIs[NamespaceAccessor[_FullContext]]c                 C  s   t | do	t | dS )Nr   	_accessorr  r  r   r   r   _is_namespace_accessor?  s   r  rK  TypeIs[_EagerAllowedImpl]c                C  s   | t jt jt jt jt jhv S )z.Return True if `impl` allows eager operations.)r   r  r  r  r  r	  rK  r   r   r   is_eager_allowedI  s   r  TypeIs[_LazyFrameCollectImpl]c                C  r&  )z4Return True if `LazyFrame.collect(impl)` is allowed.)r   r  r  r	  r  r   r   r   can_lazyframe_collectT     r  TypeIs[_LazyAllowedImpl]c                C  s$   | t jt jt jt jt jt jt jhv S )z1Return True if `DataFrame.lazy(impl)` is allowed.)r   r  r  r  r  r
  r  r  r  r   r   r   is_lazy_allowedY  s   r  TypeIs[SupportsNativeNamespace]c                 C  r  )Nr  r  r  r   r   r   has_native_namespacef  r  r  TypeIs[ArrowStreamExportable]c                 C  r  )N__arrow_c_stream__r  r  r   r   r   supports_arrow_c_streamj  r  r  left_onright_onsuffixdict[str, str]c                   s"    fdd|D }t t||S )aO  Remap join keys to avoid collisions.

    If left keys collide with the right keys, append the suffix.
    If there's no collision, let the right keys be.

    Arguments:
        left_on: Left keys.
        right_on: Right keys.
        suffix: Suffix to append to right keys.

    Returns:
        A map of old to new right keys.
    c                 3  s(    | ]}| v r|  n|V  qd S r   r   )ri  keyr  r  r   r   rk  ~  s    
z(_remap_full_join_keys.<locals>.<genexpr>)dictr  )r  r  r  right_keys_suffixedr   r  r   _remap_full_join_keysn  s   r  datarZ   contextpa.Tablec                C  sB   t dr|jjdj}|jj| |djS dt| d}t	|)zGuards `ArrowDataFrame.from_arrow` w/ safer imports.

    Arguments:
        data: Object which implements `__arrow_c_stream__`.
        context: Initialized compliant object.
    r   )r  zB'pyarrow>=14.0.0' is required for `from_arrow` for object of type rl  )
r   r   r   r  r   
_dataframe
from_arrowr   rZ  ModuleNotFoundError)r  r  rz  r  r   r   r   _into_arrow_table  s
   r  r7  c                C  s   | S )a  Visual-only marker for unstable functionality.

    Arguments:
        fn: Function to decorate.

    Returns:
        Decorated function (unchanged).

    Examples:
        >>> from narwhals._utils import unstable
        >>> @unstable
        ... def a_work_in_progress_feature(*args):
        ...     return args
        >>>
        >>> a_work_in_progress_feature.__name__
        'a_work_in_progress_feature'
        >>> a_work_in_progress_feature(1, 2, 3)
        (1, 2, 3)
    r   r?  r   r   r   unstable  s   r  formatc                   s   t  fdddD  S )a  Determines if a datetime format string is 'naive', i.e., does not include timezone information.

    A format is considered naive if it does not contain any of the following

    - '%s': Unix timestamp
    - '%z': UTC offset
    - 'Z' : UTC timezone designator

    Arguments:
        format: The datetime format string to check.

    Returns:
        bool: True if the format is naive (does not include timezone info), False otherwise.
    c                 3  s    | ]}| v V  qd S r   r   )ri  xr  r   r   rk    rP  z#_is_naive_format.<locals>.<genexpr>)z%sz%zZr,  r  r   r  r   _is_naive_format  s   r  c                   @  sV   e Zd ZdZd d!ddZd"d
dZd#ddZ	d d$ddZd%ddZe	d&ddZ
dS )'not_implementeda  Mark some functionality as unsupported.

    Arguments:
        alias: optional name used instead of the data model hook [`__set_name__`].

    Returns:
        An exception-raising [descriptor].

    Notes:
        - Attribute/method name *doesn't* need to be declared twice
        - Allows different behavior when looked up on the class vs instance
        - Allows us to use `isinstance(...)` instead of monkeypatching an attribute to the function

    Examples:
        >>> from narwhals._utils import not_implemented
        >>> class Thing:
        ...     def totally_ready(self) -> str:
        ...         return "I'm ready!"
        ...
        ...     not_ready_yet = not_implemented()
        >>>
        >>> thing = Thing()
        >>> thing.totally_ready()
        "I'm ready!"
        >>> thing.not_ready_yet()
        Traceback (most recent call last):
            ...
        NotImplementedError: 'not_ready_yet' is not implemented for: 'Thing'.
        ...
        >>> isinstance(Thing.not_ready_yet, not_implemented)
        True

    [`__set_name__`]: https://docs.python.org/3/reference/datamodel.html#object.__set_name__
    [descriptor]: https://docs.python.org/3/howto/descriptor.html
    Nalias
str | Noner   r   c                C  
   || _ d S r   )_alias)r   r  r   r   r   __init__  r  znot_implemented.__init__r   c                 C  s    dt | j d| j d| j S )N<z>: rl  )rp  r   _name_owner_namer   r   r   r   __repr__  s    znot_implemented.__repr__r   rr  namec                 C  s   |j | _| jp|| _d S r   )r   r  r  r  r   r   r  r   r   r   __set_name__  s   znot_implemented.__set_name__r   _T | Literal['raise'] | Nonetype[_T] | Noner   c                C  sD   |d u r| S t |dtj}|tjurt|}n| j}t| j| d S )Nr   )r  r   r  reprr  _raise_not_implemented_errorr  )r   r   r   rH  whor   r   r   r     s   

znot_implemented.__get__rO  r:  c                 O  s
   |  dS )Nraise)r   )r   rO  r:  r   r   r   __call__  r  znot_implemented.__call__messager>   r@   c                C  s   |  }t ||S )zAlt constructor, wraps with `@deprecated`.

        Arguments:
            message: **Static-only** deprecation message, emitted in an IDE.

        [descriptor]: https://docs.python.org/3/howto/descriptor.html
        )r$   )r  r  r  r   r   r   r$     s   	znot_implemented.deprecatedr   )r  r  r   r   r5  )r   rr  r  r   r   r   )r   r  r   r  r   r   )rO  r   r:  r   r   r   )r  r>   r   r@   )r   r   r   r   r  r  r  r   r  r6  r$   r   r   r   r   r    s    $


r  whatr  NotImplementedErrorc                C  s   | d|d}t |)Nz is not implemented for: z.

If you would like to see this functionality in `narwhals`, please open an issue at: https://github.com/narwhals-dev/narwhals/issues)r  )r  r  r  r   r   r   r    s   r  c                   @  sr   e Zd ZU dZded< ded< ded< 	 ed"d#ddZed$ddZd%ddZ	d&ddZ
d'ddZd(dd Zd!S ))requiresa#  Method decorator for raising under certain constraints.

    Attributes:
        _min_version: Minimum backend version.
        _hint: Optional suggested alternative.

    Examples:
        >>> from narwhals._utils import requires, Implementation
        >>> class SomeBackend:
        ...     _implementation = Implementation.PYARROW
        ...     _backend_version = 20, 0, 0
        ...
        ...     @requires.backend_version((9000, 0, 0))
        ...     def really_complex_feature(self) -> str:
        ...         return "hello"
        >>> backend = SomeBackend()
        >>> backend.really_complex_feature()
        Traceback (most recent call last):
            ...
        NotImplementedError: `really_complex_feature` is only available in 'pyarrow>=9000.0.0', found version '20.0.0'.
    r   _min_versionr   _hint_wrapped_namere  hintminimumr   r@   c                C  s   |  | }||_||_|S )zMethod decorator for raising below a minimum `_backend_version`.

        Arguments:
            minimum: Minimum backend version.
            hint: Optional suggested alternative.
        )__new__r  r  )r  r  r  r  r   r   r   r4  ;  s   
zrequires.backend_versionr4  c                C  s   d dd | D S )Nrl  c                 s  s    | ]}| V  qd S r   r   )ri  dr   r   r   rk  J  s    z,requires._unparse_version.<locals>.<genexpr>)rp  r3  r   r   r   _unparse_versionH  r  zrequires._unparse_versionr  rG   r   c                C  s$   d| j vr| d| j  | _ d S d S Nrl  )r  )r   r  r   r   r   _qualify_accessor_nameL  s   
zrequires._qualify_accessor_namer   r   tuple[tuple[int, ...], str]c                C  s0   t |r| |j |j}n|}|jt|jfS r   )r  r  r  r   r   r   r   )r   r   r   r   r   r   _unwrap_contextQ  s
   zrequires._unwrap_contextc             	   C  sp   |  |\}}|| jkrd S | | j}| |}d| j d| d| d|d	}| jr4| d| j }t|)N`z` is only available in 'z>=z', found version rl  
)r  r  r  r  r  r  )r   r   rM  r  r  foundr  r   r   r   _ensure_versionY  s   

 zrequires._ensure_versionr7  _Method[_IntoContextT, P, R]c                  s$    j _t d fd	d
}|S )Nr   r   rO  r9  r:  r;  r   r   c                   s     |   | g|R i |S r   )r  )r   rO  r:  r7  r   r   r   r=  i  s   
z"requires.__call__.<locals>.wrapper)r   r   rO  r9  r:  r;  r   r   )r   r  r   )r   r7  r=  r   r  r   r  d  s   zrequires.__call__N)re  )r  r   r  r   r   r@   )r4  r   r   r   )r  rG   r   r   )r   r   r   r  )r   r   r   r   )r7  r  r   r  )r   r   r   r   r   r6  r4  staticmethodr  r  r  r  r  r   r   r   r   r    s   
 


r  	str_slicer   "tuple[int | None, int | None, Any]c                 C  sH   | j d ur|| j nd }| jd ur|| jd nd }| j}|||fS )Nr7  )r  r  r  r  )r  r   r  r  r  r   r   r   convert_str_slice_to_int_slicer  s   
r  	tp_parentCallable[P, R1]<Callable[[_Constructor[_T, P, R2]], _Constructor[_T, P, R2]]c                  s   d fdd}|S )zSteal the class-level docstring from parent and attach to child `__init__`.

    Returns:
        Decorated constructor.

    Notes:
        - Passes static typing (mostly)
        - Passes at runtime
    
init_child_Constructor[_T, P, R2]r   c                  sH   | j dkrtt trt | _| S dtj  d| jd }t|)Nr  z`@zL` is only allowed to decorate an `__init__` with a class-level doc.
Method: z	
Parent: )r   r  rp  r   r   inherit_docr   r[  )r  r  r  r   r   r@    s   

zinherit_doc.<locals>.decorateN)r  r  r   r  r   )r  r@  r   r  r   r  {  s   r  object | type[Any]c                C  s@   t | tr| nt| }|jdkr|jnd}| d|j dS )Nbuiltinsre  rl  )r  rp  r   r   lstrip)r  r%  moduler   r   r   rZ    s   rZ  rF  valid_types	type[Any]rG  c         	      G  s   t | |sQddd |D }d|dt| }|rMd}t| }t|dkr.t|  d}| | d	}d
t| dt|  }| d| | d| }t|dS )a  Validate that an object is an instance of one or more specified types.

    Parameters:
        obj: The object to validate.
        *valid_types: One or more valid types that `obj` is expected to match.
        param_name: The name of the parameter being validated.
            Used to improve error message clarity.

    Raises:
        TypeError: If `obj` is not an instance of any of the provided `valid_types`.

    Examples:
        >>> from narwhals._utils import ensure_type
        >>> ensure_type(42, int, float)
        >>> ensure_type("hello", str)

        >>> ensure_type("hello", int, param_name="test")
        Traceback (most recent call last):
            ...
        TypeError: Expected 'int', got: 'str'
            test='hello'
                 ^^^^^^^
        >>> import polars as pl
        >>> import pandas as pd
        >>> df = pl.DataFrame([[1], [2], [3], [4], [5]], schema=[*"abcde"])
        >>> ensure_type(df, pd.DataFrame, param_name="df")
        Traceback (most recent call last):
            ...
        TypeError: Expected 'pandas.core.frame.DataFrame', got: 'polars.dataframe.frame.DataFrame'
            df=polars.dataframe.frame.DataFrame(...)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    z | c                 s  rN  r   )rZ  )ri  r%  r   r   r   rk    rP  zensure_type.<locals>.<genexpr>z	Expected z, got: z    (   z(...)=rR  ^r  N)r  rp  rZ  r  rR  r[  )	r  rG  r  tp_namesr  left_padr_  assign	underliner   r   r   rH    s   
!rH  c                   @  s.   e Zd ZdZdddZdd	d
ZdddZdS )_DeferredIterablezLStore a callable producing an iterable to defer collection until we need it.	into_iterCallable[[], Iterable[_T]]r   r   c                C  r  r   
_into_iter)r   r  r   r   r   r    r  z_DeferredIterable.__init__Iterator[_T]c                 c  s    |   E d H  d S r   r  r   r   r   r   __iter__  s   z_DeferredIterable.__iter__tuple[_T, ...]c                 C  s   |   }t|tr|S t|S r   )r  r  rV  )r   itr   r   r   to_tuple  s   z_DeferredIterable.to_tupleN)r  r  r   r   )r   r  )r   r  )r   r   r   r   r  r  r  r   r   r   r   r    s
    

r  @   nestedattrgetter[Any]c                 G  s"   |rd | g|R n| }t|S r  )rp  r   )r  r  r  r   r   r   deep_attrgetter  s   r  name_1c                 G  s   t |g|R  | S )z+Perform a nested attribute lookup on `obj`.)r  )r  r  r  r   r   r   deep_getattr  r  r  c                   @  s   e Zd ZdS )	CompliantN)r   r   r   r   r   r   r   r    s    r  c                   @  r   )Narwhalsa  Minimal *Narwhals-level* protocol.

    Provides access to a compliant object:

        obj: Narwhals[NativeT_co]]
        compliant: Compliant[NativeT_co] = obj._compliant

    Which itself exposes:

        implementation: Implementation = compliant.implementation
        native: NativeT_co = compliant.native

    This interface is used for revealing which `Implementation` member is associated with **either**:
    - One or more [nominal] native type(s)
    - One or more [structural] type(s)
      - where the true native type(s) are [assignable to] *at least* one of them

    These relationships are defined in the `@overload`s of `_Implementation.__get__(...)`.

    [nominal]: https://typing.python.org/en/latest/spec/glossary.html#term-nominal
    [structural]: https://typing.python.org/en/latest/spec/glossary.html#term-structural
    [assignable to]: https://typing.python.org/en/latest/spec/glossary.html#term-assignable
    r   Compliant[NativeT_co]c                 C  r   r   r   r   r   r   r   r    r   zNarwhals._compliantN)r   r  )r   r   r   r   r   r  r   r   r   r   r    s    r  c                   @  s   e Zd ZdZd=dd	Zed>ddZed?ddZed@ddZedAddZedBddZedCddZedDd!dZedEd$dZedFd'dZedGd*dZedHd-dZedId0dZedJd3dZedKd6dZedLd9dZdMd;dZd<S )N_ImplementationzDescriptor for matching an opaque `Implementation` on a generic class.

    Based on [pyright comment](https://github.com/microsoft/pyright/issues/3071#issuecomment-1043978070)
    r   r  r  r   r   r   c                 C  s
   || _ d S r   )r   r  r   r   r   r    r  z_Implementation.__set_name__r   Narwhals[NativePolars]r   ri   c                 C  r   r   r   r   r   r   r   r     r   z_Implementation.__get__Narwhals[NativePandas]rg   c                 C  r   r   r   r   r   r   r   r     r   Narwhals[NativeModin]rf   c                 C  r   r   r   r   r   r   r   r     r   Narwhals[NativeCuDF]r_   c                 C  r   r   r   r   r   r   r   r     r   Narwhals[NativePandasLike]rh   c                 C  r   r   r   r   r   r   r   r     r   Narwhals[NativeArrow]r^   c                 C  r   r   r   r   r   r   r   r     r   3Narwhals[NativePolars | NativeArrow | NativePandas]&_PolarsImpl | _PandasImpl | _ArrowImplc                 C  r   r   r   r   r   r   r   r     r   Narwhals[NativeDuckDB]ra   c                 C  r   r   r   r   r   r   r   r   "  r   Narwhals[NativeSQLFrame]rl   c                 C  r   r   r   r   r   r   r   r   $  r   Narwhals[NativeDask]r`   c                 C  r   r   r   r   r   r   r   r   (  r   Narwhals[NativeIbis]rc   c                 C  r   r   r   r   r   r   r   r   *  r   .Narwhals[NativePySpark | NativePySparkConnect]"_PySparkImpl | _PySparkConnectImplc                 C  r   r   r   r   r   r   r   r   ,  r   type[Narwhals[Any]]r@   c                 C  r   r   r   r   r   r   r   r   1  r   DataFrame[Any] | Series[Any]rb   c                 C  r   r   r   r   r   r   r   r   3  r   LazyFrame[Any]rd   c                 C  r   r   r   r   r   r   r   r   7  r   Narwhals[Any] | Nonec                 C  s   |d u r| S |j jS r   )r  r   r   r   r   r   r   9  r  N)r   r  r  r   r   r   )r   r   r   r   r   ri   )r   r!  r   r   r   rg   )r   r"  r   r   r   rf   )r   r#  r   r   r   r_   )r   r$  r   r   r   rh   )r   r%  r   r   r   r^   )r   r&  r   r   r   r'  )r   r(  r   r   r   ra   )r   r)  r   r   r   rl   )r   r*  r   r   r   r`   )r   r+  r   r   r   rc   )r   r,  r   r   r   r-  )r   r   r   r.  r   r@   )r   r/  r   r   r   rb   )r   r0  r   r   r   rd   )r   r1  r   r   r   r   )r   r   r   r   r  r    r   r   r   r   r   r    sD    
r  tblpa.Table | pa.RecordBatchReaderc                 C  s$   dd l }t| |jr|j| S | S r  )r   r  RecordBatchReaderTablefrom_batches)r2  par   r   r   to_pyarrow_table=  s   r8  sourcerx   c                C  s&   t | tr| S ddlm} t|| S )Nr   )Path)r  r   pathlibr:  )r9  r:  r   r   r   normalize_pathE  s   
r<  r   bool | Iterable[bool]n_matchSequence[bool]c                 C  s   t | tr
| f| S t| S )zEnsure the given bool or sequence of bools is the correct length.

    Stolen from https://github.com/pola-rs/polars/blob/b8bfb07a4a37a8d449d6d1841e345817431142df/py-polars/polars/_utils/various.py#L580-L594
    )r  r"  rV  )r   r>  r   r   r   extend_boolM  s   r@  c                   @  r   )
_NoDefault
NO_DEFAULTr   r   c                 C  r   )Nz<no_default>r   r   r   r   r   r  ]  r   z_NoDefault.__repr__Nr5  )r   r   r   
no_defaultr  r   r   r   r   rA  X  s    rA  )r   r   r   r<   )rH  r   r   r   )rO  r   r   rP  )rU  r   r   r   )rU  rX  r   r"  )r_  r`  r   ra  )rM  rd  r   r   )ro  rp  rq  rr  r   rs  )ro  rv  rq  rr  r   rw  )ro  rp  rq  rx  r   ry  )ro  rv  rq  rx  r   rz  )ro  rp  rq  r{  r   r|  )ro  rv  rq  r{  r   r}  )ro  r   rq  r~  r   r  )ro  r   rq  r   r   r"  )r  r  r   r   )r  r   r  r  r   r   )r  r  r   r   r   )r  r   r  r  r  r  r   r   )r  r   r   r   )r  r  r   r  )r  r   r  r   r   r  )r  r  r  r   r   r"  )r  r   rO  r"  r  r  r   r   )r  rf  r  r~   r   r  )r   r  r   r"  )r  )r  rf  r   r  r  r   r   r   )r  r   r  r  r  r"  r   r   )r  r	  r   r
  )r  r   r   r  )r  r   r   r  )r  r	  r   r  )r  r   r   r  )r  r   r   r  )r  r   r   r  )r  r   r   r   )r  r   r   r"  )r  r   r%  rr  r   r&  )r(  r)  r   r*  )r  r   r%  rr  r   r
  )r  r1  r  r1  r2  r"  r   r"  )r4  r   r5  r"  r   r6  )rB  rf  rC  rD  r   rE  )rJ  r   rK  r   r   r   )r  rf  r  rf  r   rg  )r   rf  r   r   )rs  rt  ru  rv  r   rw  )
r  rq   r   rw   r~  r  r  r  r   r"  )r  r   r   r   )r  r   r  r  r   r   )r  r   r   r  )r  r   r  r   r   r"  )r  r  r   r  )r  r  r   r  )r  r  r   r  )r  r   r   r  )rK  r   r   r  )rK  r   r   r  )rK  r   r   r  )r  r   r   r  )r  r   r   r  )r  rf  r  rf  r  r   r   r  )r  rZ   r  r   r   r  )r7  r   r   r   )r  r   r   r"  )r  r   r  r   r   r  )r  r   r   r   r   r  )r  r  r   r  )r  r  r   r   )r  r   r  r  rG  r   r   r   )r  r   r  r   r   r  )r  r   r  r   r  r   r   r   )r2  r3  r   r  )r9  rx   r   r   )r   r=  r>  rf  r   r?  ('  
__future__r   rU  rg  syscollections.abcr   r   r   r   r   r   datetimer	   enumr
   r   	functoolsr   r   r   r   importlib.utilr   inspectr   r   	itertoolsr   operatorr   secretsr   typingr   r   r   r   r   r   r   r   r   r   r    narwhals._enumr!   narwhals._exceptionsr"   narwhals._typing_compatr#   r$   narwhals.dependenciesr%   r&   r'   r(   r)   r*   r+   r,   r-   r.   r/   r0   r1   r2   r3   r4   r5   r6   r7   narwhals.exceptionsr8   r9   r:   r;   typesr<   r   r]  r   r^  r   r7  typing_extensionsr=   r>   r?   r@   rA   rB   narwhals._compliantrC   rD   rE   !narwhals._compliant.any_namespacerF   narwhals._compliant.typingrG   rH   rI   rJ   r   rL   narwhals._nativerM   rN   rO   rP   rQ   rR   rS   rT   rU   rV   rW   rX   narwhals._translaterY   rZ   r[   narwhals._typingr\   r]   r^   r_   r`   ra   rb   rc   rd   re   rf   rg   rh   ri   rj   rk   rl   r   rn   ro   r  rq   r   rs   narwhals.typingrt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r   r  r  r  r	  r
  r  r  r  r  r  r  rC  r  r  r4  rT  rW  rS  rc  rJ  ru  r  r  r  r  r  r  r  version_infor  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r!  r$  r'  r.  r0  r3  rA  rI  re  r  rr  r  r  r  r  r  objectr  r  r  r  r  r  r#  r  r  r  r  r  r  r  r  r  r  r  r  r  r  r  rZ  rH  r  r  r  r  r  r  r8  r<  r@  rA  rC  rp  r  r   r   r   r   <module>   s    4T 	8LLL  	
\#V/)C-
	)

V	V	/
6