Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

REGR: fix return class in _constructor_from_mgr for simple subclasses #55764

4 changes: 2 additions & 2 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -646,7 +646,7 @@ def _constructor(self) -> Callable[..., DataFrame]:
return DataFrame

def _constructor_from_mgr(self, mgr, axes):
if self._constructor is DataFrame:
if type(self) is DataFrame:
ivirshup marked this conversation as resolved.
Show resolved Hide resolved
# we are pandas.DataFrame (or a subclass that doesn't override _constructor)
return self._from_mgr(mgr, axes=axes)
ivirshup marked this conversation as resolved.
Show resolved Hide resolved
else:
Expand All @@ -659,7 +659,7 @@ def _sliced_from_mgr(self, mgr, axes) -> Series:
return Series._from_mgr(mgr, axes)

def _constructor_sliced_from_mgr(self, mgr, axes):
if self._constructor_sliced is Series:
if type(self) is DataFrame:
ser = self._sliced_from_mgr(mgr, axes)
ser._name = None # caller is responsible for setting real name
return ser
Expand Down
6 changes: 2 additions & 4 deletions pandas/core/series.py
Original file line number Diff line number Diff line change
Expand Up @@ -632,7 +632,7 @@ def _constructor(self) -> Callable[..., Series]:
return Series

def _constructor_from_mgr(self, mgr, axes):
if self._constructor is Series:
if type(self) is Series:
# we are pandas.Series (or a subclass that doesn't override _constructor)
ser = self._from_mgr(mgr, axes=axes)
ser._name = None # caller is responsible for setting real name
Expand All @@ -657,9 +657,7 @@ def _expanddim_from_mgr(self, mgr, axes) -> DataFrame:
return DataFrame._from_mgr(mgr, axes=mgr.axes)

def _constructor_expanddim_from_mgr(self, mgr, axes):
from pandas.core.frame import DataFrame

if self._constructor_expanddim is DataFrame:
if type(self) is Series:
return self._expanddim_from_mgr(mgr, axes)
assert axes is mgr.axes
return self._constructor_expanddim(mgr)
Expand Down
3 changes: 3 additions & 0 deletions pandas/tests/frame/methods/test_reindex_like.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ def test_reindex_like_methods(self, method, expected_values):
result = df.reindex_like(df, method=method, tolerance=[0, 0, 0, 0])
tm.assert_frame_equal(df, result)

@pytest.mark.filterwarnings(
"ignore:Passing a BlockManager|Passing a SingleBlockManager:DeprecationWarning"
)
def test_reindex_like_subclass(self):
# https://github.com/pandas-dev/pandas/issues/31925
class MyDataFrame(DataFrame):
Expand Down
18 changes: 18 additions & 0 deletions pandas/tests/frame/test_subclass.py
Original file line number Diff line number Diff line change
Expand Up @@ -773,3 +773,21 @@ def test_constructor_with_metadata():
)
subset = df[["A", "B"]]
assert isinstance(subset, MySubclassWithMetadata)


class SimpleSubClass(DataFrame):
"""A subclass of DataFrame that does not define a constructor."""


class TestSubclassWithoutConstructor:
def test_copy(self):
expected = DataFrame({"a": [1, 2, 3]})
result = SimpleSubClass(expected).copy()

tm.assert_frame_equal(result, expected)
ivirshup marked this conversation as resolved.
Show resolved Hide resolved

def test_groupby(self):
df = SimpleSubClass(DataFrame({"a": [1, 2, 3]}))

for _, v in df.groupby("a"):
assert isinstance(v, DataFrame)