diff --git a/docs/api-completeness/index.md b/docs/api-completeness/index.md index 3daba31ca..331817920 100644 --- a/docs/api-completeness/index.md +++ b/docs/api-completeness/index.md @@ -1,10 +1,5 @@ # API Completeness -Narwhals has two different level of support for libraries: "full" and "interchange". - -Libraries for which we have full support we intend to support the whole Narwhals API, -however this is a continuous work in progress. - In the following section it is possible to check which method is implemented for which class and backend. @@ -12,3 +7,4 @@ class and backend. - By design, Polars supports all the methods of the Narwhals API. - "pandas-like" means pandas, cuDF and Modin. + - "spark-like" means PySpark, but we may extend this to also cover SQLFrame. diff --git a/narwhals/functions.py b/narwhals/functions.py index a8d098a39..f10a397f7 100644 --- a/narwhals/functions.py +++ b/narwhals/functions.py @@ -10,6 +10,7 @@ from typing import Sequence from typing import TypeVar from typing import Union +from typing import overload from narwhals._expression_parsing import extract_compliant from narwhals._pandas_like.utils import broadcast_align_and_extract_native @@ -38,7 +39,9 @@ from narwhals.dtypes import DType from narwhals.schema import Schema from narwhals.series import Series + from narwhals.typing import IntoDataFrameT from narwhals.typing import IntoExpr + from narwhals.typing import IntoFrameT from narwhals.typing import IntoSeriesT class ArrowStreamExportable(Protocol): @@ -47,11 +50,35 @@ def __arrow_c_stream__( ) -> object: ... +@overload def concat( - items: Iterable[FrameT], + items: Iterable[DataFrame[IntoDataFrameT]], *, how: Literal["horizontal", "vertical", "diagonal"] = "vertical", -) -> FrameT: +) -> DataFrame[IntoDataFrameT]: ... + + +@overload +def concat( + items: Iterable[LazyFrame[IntoFrameT]], + *, + how: Literal["horizontal", "vertical", "diagonal"] = "vertical", +) -> LazyFrame[IntoFrameT]: ... + + +@overload +def concat( + items: Iterable[DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]], + *, + how: Literal["horizontal", "vertical", "diagonal"] = "vertical", +) -> DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]: ... + + +def concat( + items: Iterable[DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]], + *, + how: Literal["horizontal", "vertical", "diagonal"] = "vertical", +) -> DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]: """Concatenate multiple DataFrames, LazyFrames into a single entity. Arguments: @@ -197,7 +224,7 @@ def concat( validate_laziness(items) first_item = items[0] plx = first_item.__narwhals_namespace__() - return first_item._from_compliant_dataframe( # type: ignore[return-value] + return first_item._from_compliant_dataframe( plx.concat([df._compliant_frame for df in items], how=how), ) diff --git a/narwhals/stable/v1/__init__.py b/narwhals/stable/v1/__init__.py index 689ab53dd..e8fd5a921 100644 --- a/narwhals/stable/v1/__init__.py +++ b/narwhals/stable/v1/__init__.py @@ -3292,25 +3292,33 @@ def max_horizontal(*exprs: IntoExpr | Iterable[IntoExpr]) -> Expr: @overload def concat( - items: Iterable[DataFrame[Any]], + items: Iterable[DataFrame[IntoDataFrameT]], *, how: Literal["horizontal", "vertical", "diagonal"] = "vertical", -) -> DataFrame[Any]: ... +) -> DataFrame[IntoDataFrameT]: ... + + +@overload +def concat( + items: Iterable[LazyFrame[IntoFrameT]], + *, + how: Literal["horizontal", "vertical", "diagonal"] = "vertical", +) -> LazyFrame[IntoFrameT]: ... @overload def concat( - items: Iterable[LazyFrame[Any]], + items: Iterable[DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]], *, how: Literal["horizontal", "vertical", "diagonal"] = "vertical", -) -> LazyFrame[Any]: ... +) -> DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]: ... def concat( - items: Iterable[DataFrame[Any] | LazyFrame[Any]], + items: Iterable[DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]], *, how: Literal["horizontal", "vertical", "diagonal"] = "vertical", -) -> DataFrame[Any] | LazyFrame[Any]: +) -> DataFrame[IntoDataFrameT] | LazyFrame[IntoFrameT]: """Concatenate multiple DataFrames, LazyFrames into a single entity. Arguments: @@ -3446,7 +3454,7 @@ def concat( │ 4 ┆ null ┆ y │ └─────┴──────┴──────┘ """ - return _stableify(nw.concat(items, how=how)) # type: ignore[no-any-return] + return _stableify(nw.concat(items, how=how)) def concat_str( diff --git a/tests/frame/invalid_test.py b/tests/frame/invalid_test.py index af600321a..5d2f7b45a 100644 --- a/tests/frame/invalid_test.py +++ b/tests/frame/invalid_test.py @@ -40,7 +40,7 @@ def test_validate_laziness() -> None: TypeError, match=("The items to concatenate should either all be eager, or all lazy"), ): - nw.concat([nw.from_native(df, eager_only=True), nw.from_native(df).lazy()]) # type: ignore[list-item] + nw.concat([nw.from_native(df, eager_only=True), nw.from_native(df).lazy()]) @pytest.mark.slow