Skip to content

Commit

Permalink
Fix pd.concat to accept None values as input. (#858)
Browse files Browse the repository at this point in the history
* Fix pd.concat to accept None values as input.

* Add test

* a few changes

* comment

---------

Co-authored-by: Torsten Wörtwein <[email protected]>
  • Loading branch information
amgcc and twoertwein authored Feb 21, 2024
1 parent daa3f27 commit 82ed4f1
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 5 deletions.
27 changes: 23 additions & 4 deletions pandas-stubs/core/reshape/concat.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ from pandas import (
DataFrame,
Series,
)
from typing_extensions import Never

from pandas._typing import (
Axis,
AxisColumn,
AxisIndex,
HashableT1,
Expand All @@ -24,9 +26,23 @@ from pandas._typing import (

@overload
def concat(
objs: Iterable[DataFrame] | Mapping[HashableT1, DataFrame],
objs: Iterable[None] | Mapping[HashableT1, None],
*,
axis: AxisIndex = ...,
axis: Axis = ...,
join: Literal["inner", "outer"] = ...,
ignore_index: bool = ...,
keys: Iterable[HashableT2] = ...,
levels: Sequence[list[HashableT3] | tuple[HashableT3, ...]] = ...,
names: list[HashableT4] = ...,
verify_integrity: bool = ...,
sort: bool = ...,
copy: bool = ...,
) -> Never: ...
@overload
def concat( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
objs: Iterable[DataFrame | None] | Mapping[HashableT1, DataFrame | None],
*,
axis: Axis = ...,
join: Literal["inner", "outer"] = ...,
ignore_index: bool = ...,
keys: Iterable[HashableT2] = ...,
Expand All @@ -38,7 +54,7 @@ def concat(
) -> DataFrame: ...
@overload
def concat(
objs: Iterable[Series] | Mapping[HashableT1, Series],
objs: Iterable[Series | None] | Mapping[HashableT1, Series | None],
*,
axis: AxisIndex = ...,
join: Literal["inner", "outer"] = ...,
Expand All @@ -52,7 +68,10 @@ def concat(
) -> Series: ...
@overload
def concat(
objs: Iterable[Series | DataFrame] | Mapping[HashableT1, Series | DataFrame],
objs: (
Iterable[Series | DataFrame | None]
| Mapping[HashableT1, Series | DataFrame | None]
),
*,
axis: AxisColumn,
join: Literal["inner", "outer"] = ...,
Expand Down
29 changes: 28 additions & 1 deletion tests/test_pandas.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@

# TODO: github.com/pandas-dev/pandas/issues/55023
import pytest
from typing_extensions import assert_type
from typing_extensions import (
Never,
assert_type,
)

from pandas._libs.missing import NAType
from pandas._libs.tslibs import NaTType
Expand Down Expand Up @@ -49,6 +52,30 @@ def test_types_to_datetime() -> None:
)


def test_types_concat_none() -> None:
"""Test concatenation with None values."""
series = pd.Series([7, -5, 10])
df = pd.DataFrame({"a": [7, -5, 10]})

check(assert_type(pd.concat([None, series]), pd.Series), pd.Series)
check(assert_type(pd.concat([None, df]), pd.DataFrame), pd.DataFrame)
check(
assert_type(pd.concat([None, series, df], axis=1), pd.DataFrame), pd.DataFrame
)

check(assert_type(pd.concat({"a": None, "b": series}), pd.Series), pd.Series)
check(assert_type(pd.concat({"a": None, "b": df}), pd.DataFrame), pd.DataFrame)
check(
assert_type(pd.concat({"a": None, "b": series, "c": df}, axis=1), pd.DataFrame),
pd.DataFrame,
)

if TYPE_CHECKING_INVALID_USAGE:
# using assert_type as otherwise the second call would not be type-checked
assert_type(pd.concat({"a": None}), Never)
assert_type(pd.concat([None]), Never)


def test_types_concat() -> None:
s: pd.Series = pd.Series([0, 1, -10])
s2: pd.Series = pd.Series([7, -5, 10])
Expand Down

0 comments on commit 82ed4f1

Please sign in to comment.