Skip to content

Commit 82ed4f1

Browse files
amgcctwoertwein
andauthored
Fix pd.concat to accept None values as input. (pandas-dev#858)
* Fix pd.concat to accept None values as input. * Add test * a few changes * comment --------- Co-authored-by: Torsten Wörtwein <[email protected]>
1 parent daa3f27 commit 82ed4f1

File tree

2 files changed

+51
-5
lines changed

2 files changed

+51
-5
lines changed

pandas-stubs/core/reshape/concat.pyi

+23-4
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,10 @@ from pandas import (
1212
DataFrame,
1313
Series,
1414
)
15+
from typing_extensions import Never
1516

1617
from pandas._typing import (
18+
Axis,
1719
AxisColumn,
1820
AxisIndex,
1921
HashableT1,
@@ -24,9 +26,23 @@ from pandas._typing import (
2426

2527
@overload
2628
def concat(
27-
objs: Iterable[DataFrame] | Mapping[HashableT1, DataFrame],
29+
objs: Iterable[None] | Mapping[HashableT1, None],
2830
*,
29-
axis: AxisIndex = ...,
31+
axis: Axis = ...,
32+
join: Literal["inner", "outer"] = ...,
33+
ignore_index: bool = ...,
34+
keys: Iterable[HashableT2] = ...,
35+
levels: Sequence[list[HashableT3] | tuple[HashableT3, ...]] = ...,
36+
names: list[HashableT4] = ...,
37+
verify_integrity: bool = ...,
38+
sort: bool = ...,
39+
copy: bool = ...,
40+
) -> Never: ...
41+
@overload
42+
def concat( # type: ignore[overload-overlap] # pyright: ignore[reportOverlappingOverload]
43+
objs: Iterable[DataFrame | None] | Mapping[HashableT1, DataFrame | None],
44+
*,
45+
axis: Axis = ...,
3046
join: Literal["inner", "outer"] = ...,
3147
ignore_index: bool = ...,
3248
keys: Iterable[HashableT2] = ...,
@@ -38,7 +54,7 @@ def concat(
3854
) -> DataFrame: ...
3955
@overload
4056
def concat(
41-
objs: Iterable[Series] | Mapping[HashableT1, Series],
57+
objs: Iterable[Series | None] | Mapping[HashableT1, Series | None],
4258
*,
4359
axis: AxisIndex = ...,
4460
join: Literal["inner", "outer"] = ...,
@@ -52,7 +68,10 @@ def concat(
5268
) -> Series: ...
5369
@overload
5470
def concat(
55-
objs: Iterable[Series | DataFrame] | Mapping[HashableT1, Series | DataFrame],
71+
objs: (
72+
Iterable[Series | DataFrame | None]
73+
| Mapping[HashableT1, Series | DataFrame | None]
74+
),
5675
*,
5776
axis: AxisColumn,
5877
join: Literal["inner", "outer"] = ...,

tests/test_pandas.py

+28-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,10 @@
1717

1818
# TODO: github.com/pandas-dev/pandas/issues/55023
1919
import pytest
20-
from typing_extensions import assert_type
20+
from typing_extensions import (
21+
Never,
22+
assert_type,
23+
)
2124

2225
from pandas._libs.missing import NAType
2326
from pandas._libs.tslibs import NaTType
@@ -49,6 +52,30 @@ def test_types_to_datetime() -> None:
4952
)
5053

5154

55+
def test_types_concat_none() -> None:
56+
"""Test concatenation with None values."""
57+
series = pd.Series([7, -5, 10])
58+
df = pd.DataFrame({"a": [7, -5, 10]})
59+
60+
check(assert_type(pd.concat([None, series]), pd.Series), pd.Series)
61+
check(assert_type(pd.concat([None, df]), pd.DataFrame), pd.DataFrame)
62+
check(
63+
assert_type(pd.concat([None, series, df], axis=1), pd.DataFrame), pd.DataFrame
64+
)
65+
66+
check(assert_type(pd.concat({"a": None, "b": series}), pd.Series), pd.Series)
67+
check(assert_type(pd.concat({"a": None, "b": df}), pd.DataFrame), pd.DataFrame)
68+
check(
69+
assert_type(pd.concat({"a": None, "b": series, "c": df}, axis=1), pd.DataFrame),
70+
pd.DataFrame,
71+
)
72+
73+
if TYPE_CHECKING_INVALID_USAGE:
74+
# using assert_type as otherwise the second call would not be type-checked
75+
assert_type(pd.concat({"a": None}), Never)
76+
assert_type(pd.concat([None]), Never)
77+
78+
5279
def test_types_concat() -> None:
5380
s: pd.Series = pd.Series([0, 1, -10])
5481
s2: pd.Series = pd.Series([7, -5, 10])

0 commit comments

Comments
 (0)