Skip to content

Commit e6d3783

Browse files
gioiabMeeseeksDev[bot]
authored and
MeeseeksDev[bot]
committed
Backport PR pandas-dev#25230: BUG: Fix regression in DataFrame.apply causing RecursionError
1 parent 7f44027 commit e6d3783

File tree

4 files changed

+21
-9
lines changed

4 files changed

+21
-9
lines changed

doc/source/whatsnew/v0.24.2.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ Fixed Regressions
2121
^^^^^^^^^^^^^^^^^
2222

2323
- Fixed regression in :meth:`DataFrame.all` and :meth:`DataFrame.any` where ``bool_only=True`` was ignored (:issue:`25101`)
24-
2524
- Fixed issue in ``DataFrame`` construction with passing a mixed list of mixed types could segfault. (:issue:`25075`)
25+
- Fixed regression in :meth:`DataFrame.apply` causing ``RecursionError`` when ``dict``-like classes were passed as argument. (:issue:`25196`)
2626

2727
.. _whatsnew_0242.enhancements:
2828

pandas/core/dtypes/inference.py

+8-5
Original file line numberDiff line numberDiff line change
@@ -397,12 +397,15 @@ def is_dict_like(obj):
397397
True
398398
>>> is_dict_like([1, 2, 3])
399399
False
400+
>>> is_dict_like(dict)
401+
False
402+
>>> is_dict_like(dict())
403+
True
400404
"""
401-
for attr in ("__getitem__", "keys", "__contains__"):
402-
if not hasattr(obj, attr):
403-
return False
404-
405-
return True
405+
dict_like_attrs = ("__getitem__", "keys", "__contains__")
406+
return (all(hasattr(obj, attr) for attr in dict_like_attrs)
407+
# [GH 25196] exclude classes
408+
and not isinstance(obj, type))
406409

407410

408411
def is_named_tuple(obj):

pandas/tests/dtypes/test_inference.py

+5-3
Original file line numberDiff line numberDiff line change
@@ -159,13 +159,15 @@ def test_is_nested_list_like_fails(obj):
159159

160160

161161
@pytest.mark.parametrize(
162-
"ll", [{}, {'A': 1}, Series([1])])
162+
"ll", [{}, {'A': 1}, Series([1]), collections.defaultdict()])
163163
def test_is_dict_like_passes(ll):
164164
assert inference.is_dict_like(ll)
165165

166166

167-
@pytest.mark.parametrize(
168-
"ll", ['1', 1, [1, 2], (1, 2), range(2), Index([1])])
167+
@pytest.mark.parametrize("ll", [
168+
'1', 1, [1, 2], (1, 2), range(2), Index([1]),
169+
dict, collections.defaultdict, Series
170+
])
169171
def test_is_dict_like_fails(ll):
170172
assert not inference.is_dict_like(ll)
171173

pandas/tests/frame/test_apply.py

+7
Original file line numberDiff line numberDiff line change
@@ -318,6 +318,13 @@ def test_apply_reduce_Series(self, float_frame):
318318
result = float_frame.apply(np.mean, axis=1)
319319
assert_series_equal(result, expected)
320320

321+
def test_apply_reduce_rows_to_dict(self):
322+
# GH 25196
323+
data = pd.DataFrame([[1, 2], [3, 4]])
324+
expected = pd.Series([{0: 1, 1: 3}, {0: 2, 1: 4}])
325+
result = data.apply(dict)
326+
assert_series_equal(result, expected)
327+
321328
def test_apply_differently_indexed(self):
322329
df = DataFrame(np.random.randn(20, 10))
323330

0 commit comments

Comments
 (0)