Skip to content

Add missing __finalize__ calls in indexers/iterators #46101

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

Merged
merged 9 commits into from
Apr 26, 2022
4 changes: 2 additions & 2 deletions pandas/core/frame.py
Original file line number Diff line number Diff line change
Expand Up @@ -1332,7 +1332,7 @@ def iterrows(self) -> Iterable[tuple[Hashable, Series]]:
columns = self.columns
klass = self._constructor_sliced
for k, v in zip(self.index, self.values):
s = klass(v, index=columns, name=k)
s = klass(v, index=columns, name=k).__finalize__(self)
yield k, s

def itertuples(
Expand Down Expand Up @@ -3444,7 +3444,7 @@ def _ixs(self, i: int, axis: int = 0):
index=self.columns,
name=self.index[i],
dtype=new_values.dtype,
)
).__finalize__(self)
result._set_is_copy(self, copy=copy)
return result

Expand Down
2 changes: 1 addition & 1 deletion pandas/core/generic.py
Original file line number Diff line number Diff line change
Expand Up @@ -3894,7 +3894,7 @@ class animal locomotion
index=self.columns,
name=self.index[loc],
dtype=new_values.dtype,
)
).__finalize__(self)
elif is_scalar(loc):
result = self.iloc[:, slice(loc, loc + 1)]
elif axis == 1:
Expand Down
37 changes: 37 additions & 0 deletions pandas/tests/generic/test_finalize.py
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,7 @@
(pd.Series, [1], round),
(pd.DataFrame, frame_data, operator.methodcaller("take", [0, 0])),
(pd.DataFrame, frame_mi_data, operator.methodcaller("xs", "a")),
(pd.DataFrame, frame_data, operator.methodcaller("xs", 0)),
(pd.Series, (1, mi), operator.methodcaller("xs", "a")),
(pd.DataFrame, frame_data, operator.methodcaller("get", "A")),
(
Expand Down Expand Up @@ -768,3 +769,39 @@ def test_finalize_frame_series_name():
df = pd.DataFrame({"name": [1, 2]})
result = pd.Series([1, 2]).__finalize__(df)
assert result.name is None


@pytest.mark.parametrize(
"locindexer",
[
lambda x: x.iloc[0], # returns Series
lambda x: x.iloc[:-1],
lambda x: x.iloc[[0, 1]],
lambda x: x.iloc[[True, True, False]],
lambda x: x.loc["idxA"], # returns Series
lambda x: x.loc[["idxA", "idxB"]],
lambda x: x.loc["idxA":"idxB"],
lambda x: x.loc[[True, True, False]],
lambda x: x.loc[
pd.Series(
data=[True, True, False, True], index=["idxA", "idxB", "idxC", "idxD"]
)
],
lambda x: x.loc[pd.Index(data=["idxA", "idxC"])],
],
)
def test_finalize_locators(locindexer):
df = pd.DataFrame(
{"A": [1, 2, 3], "B": [3, 4, 5], "C": [7, 8, 9]}, index=["idxA", "idxB", "idxC"]
)
df.attrs["A"] = 1
result = locindexer(df)
assert result.attrs == {"A": 1}


@pytest.mark.parametrize("iterator", ["iterrows", "items"])
def test_finalize_iterators(iterator):
df = pd.DataFrame({"A": [1]})
df.attrs["A"] = 1
for _, row in getattr(df, iterator)():
assert row.attrs == {"A": 1}