Skip to content

Commit 49bc8d8

Browse files
authored
TYP: require _update_inplace gets Frame/Series, never BlockManager (#33074)
* TYP: require _update_inplace gets BlockManager * standardize on requiring Series/DataFrame, never BlockManager
1 parent d8d1dc9 commit 49bc8d8

File tree

6 files changed

+38
-47
lines changed

6 files changed

+38
-47
lines changed

pandas/core/base.py

+2-13
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
from pandas.compat.numpy import function as nv
1414
from pandas.errors import AbstractMethodError
1515
from pandas.util._decorators import cache_readonly, doc
16-
from pandas.util._validators import validate_bool_kwarg
1716

1817
from pandas.core.dtypes.cast import is_nested_object
1918
from pandas.core.dtypes.common import (
@@ -1505,18 +1504,14 @@ def factorize(self, sort=False, na_sentinel=-1):
15051504
def searchsorted(self, value, side="left", sorter=None) -> np.ndarray:
15061505
return algorithms.searchsorted(self._values, value, side=side, sorter=sorter)
15071506

1508-
def drop_duplicates(self, keep="first", inplace=False):
1509-
inplace = validate_bool_kwarg(inplace, "inplace")
1507+
def drop_duplicates(self, keep="first"):
15101508
if isinstance(self, ABCIndexClass):
15111509
if self.is_unique:
15121510
return self._shallow_copy()
15131511

15141512
duplicated = self.duplicated(keep=keep)
15151513
result = self[np.logical_not(duplicated)]
1516-
if inplace:
1517-
return self._update_inplace(result)
1518-
else:
1519-
return result
1514+
return result
15201515

15211516
def duplicated(self, keep="first"):
15221517
if isinstance(self, ABCIndexClass):
@@ -1527,9 +1522,3 @@ def duplicated(self, keep="first"):
15271522
return self._constructor(
15281523
duplicated(self, keep=keep), index=self.index
15291524
).__finalize__(self)
1530-
1531-
# ----------------------------------------------------------------------
1532-
# abstracts
1533-
1534-
def _update_inplace(self, result, verify_is_copy=True, **kwargs):
1535-
raise AbstractMethodError(self)

pandas/core/frame.py

+11-9
Original file line numberDiff line numberDiff line change
@@ -3042,16 +3042,16 @@ def query(self, expr, inplace=False, **kwargs):
30423042
res = self.eval(expr, **kwargs)
30433043

30443044
try:
3045-
new_data = self.loc[res]
3045+
result = self.loc[res]
30463046
except ValueError:
30473047
# when res is multi-dimensional loc raises, but this is sometimes a
30483048
# valid query
3049-
new_data = self[res]
3049+
result = self[res]
30503050

30513051
if inplace:
3052-
self._update_inplace(new_data)
3052+
self._update_inplace(result)
30533053
else:
3054-
return new_data
3054+
return result
30553055

30563056
def eval(self, expr, inplace=False, **kwargs):
30573057
"""
@@ -4684,7 +4684,7 @@ def drop_duplicates(
46844684
result.index = ibase.default_index(len(result))
46854685

46864686
if inplace:
4687-
self._update_inplace(result._data)
4687+
self._update_inplace(result)
46884688
return None
46894689
else:
46904690
return result
@@ -4803,10 +4803,11 @@ def sort_values(
48034803
if ignore_index:
48044804
new_data.axes[1] = ibase.default_index(len(indexer))
48054805

4806+
result = self._constructor(new_data)
48064807
if inplace:
4807-
return self._update_inplace(new_data)
4808+
return self._update_inplace(result)
48084809
else:
4809-
return self._constructor(new_data).__finalize__(self)
4810+
return result.__finalize__(self)
48104811

48114812
def sort_index(
48124813
self,
@@ -4938,10 +4939,11 @@ def sort_index(
49384939
if ignore_index:
49394940
new_data.axes[1] = ibase.default_index(len(indexer))
49404941

4942+
result = self._constructor(new_data)
49414943
if inplace:
4942-
return self._update_inplace(new_data)
4944+
return self._update_inplace(result)
49434945
else:
4944-
return self._constructor(new_data).__finalize__(self)
4946+
return result.__finalize__(self)
49454947

49464948
def value_counts(
49474949
self,

pandas/core/generic.py

+16-14
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,7 @@ def _single_replace(self, to_replace, method, inplace, limit):
147147
result = pd.Series(values, index=self.index, dtype=self.dtype).__finalize__(self)
148148

149149
if inplace:
150-
self._update_inplace(result._data)
150+
self._update_inplace(result)
151151
return
152152

153153
return result
@@ -988,7 +988,7 @@ def rename(
988988
result._clear_item_cache()
989989

990990
if inplace:
991-
self._update_inplace(result._data)
991+
self._update_inplace(result)
992992
return None
993993
else:
994994
return result.__finalize__(self)
@@ -3957,15 +3957,15 @@ def _update_inplace(self, result, verify_is_copy: bool_t = True) -> None:
39573957
39583958
Parameters
39593959
----------
3960+
result : same type as self
39603961
verify_is_copy : bool, default True
39613962
Provide is_copy checks.
39623963
"""
39633964
# NOTE: This does *not* call __finalize__ and that's an explicit
39643965
# decision that we may revisit in the future.
3965-
39663966
self._reset_cache()
39673967
self._clear_item_cache()
3968-
self._data = getattr(result, "_data", result)
3968+
self._data = result._data
39693969
self._maybe_update_cacher(verify_is_copy=verify_is_copy)
39703970

39713971
def add_prefix(self: FrameOrSeries, prefix: str) -> FrameOrSeries:
@@ -6107,15 +6107,15 @@ def fillna(
61076107
value=value, limit=limit, inplace=inplace, downcast=downcast
61086108
)
61096109
elif isinstance(value, ABCDataFrame) and self.ndim == 2:
6110-
new_data = self.where(self.notna(), value)
6110+
new_data = self.where(self.notna(), value)._data
61116111
else:
61126112
raise ValueError(f"invalid fill value with a {type(value)}")
61136113

6114+
result = self._constructor(new_data)
61146115
if inplace:
6115-
self._update_inplace(new_data)
6116-
return None
6116+
return self._update_inplace(result)
61176117
else:
6118-
return self._constructor(new_data).__finalize__(self)
6118+
return result.__finalize__(self)
61196119

61206120
def ffill(
61216121
self: FrameOrSeries,
@@ -6627,10 +6627,11 @@ def replace(
66276627
f'Invalid "to_replace" type: {repr(type(to_replace).__name__)}'
66286628
)
66296629

6630+
result = self._constructor(new_data)
66306631
if inplace:
6631-
self._update_inplace(new_data)
6632+
return self._update_inplace(result)
66326633
else:
6633-
return self._constructor(new_data).__finalize__(self)
6634+
return result.__finalize__(self)
66346635

66356636
_shared_docs[
66366637
"interpolate"
@@ -7231,7 +7232,7 @@ def _clip_with_scalar(self, lower, upper, inplace: bool_t = False):
72317232
result[mask] = np.nan
72327233

72337234
if inplace:
7234-
self._update_inplace(result)
7235+
return self._update_inplace(result)
72357236
else:
72367237
return result
72377238

@@ -8641,7 +8642,8 @@ def _where(
86418642
new_data = self._data.putmask(
86428643
mask=cond, new=other, align=align, axis=block_axis,
86438644
)
8644-
self._update_inplace(new_data)
8645+
result = self._constructor(new_data)
8646+
return self._update_inplace(result)
86458647

86468648
else:
86478649
new_data = self._data.where(
@@ -8652,8 +8654,8 @@ def _where(
86528654
try_cast=try_cast,
86538655
axis=block_axis,
86548656
)
8655-
8656-
return self._constructor(new_data).__finalize__(self)
8657+
result = self._constructor(new_data)
8658+
return result.__finalize__(self)
86578659

86588660
_shared_docs[
86598661
"where"

pandas/core/indexes/base.py

-4
Original file line numberDiff line numberDiff line change
@@ -534,10 +534,6 @@ def _shallow_copy_with_infer(self, values, **kwargs):
534534
attributes.pop("tz", None)
535535
return Index(values, **attributes)
536536

537-
def _update_inplace(self, result, **kwargs):
538-
# guard when called from IndexOpsMixin
539-
raise TypeError("Index can't be updated inplace")
540-
541537
def is_(self, other) -> bool:
542538
"""
543539
More flexible, faster check like ``is`` but that works through views.

pandas/core/ops/methods.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ def f(self, other):
9898
# this makes sure that we are aligned like the input
9999
# we are updating inplace so we want to ignore is_copy
100100
self._update_inplace(
101-
result.reindex_like(self, copy=False)._data, verify_is_copy=False
101+
result.reindex_like(self, copy=False), verify_is_copy=False
102102
)
103103

104104
return self

pandas/core/series.py

+8-6
Original file line numberDiff line numberDiff line change
@@ -418,10 +418,6 @@ def _set_axis(self, axis: int, labels, fastpath: bool = False) -> None:
418418
# The ensure_index call aabove ensures we have an Index object
419419
self._data.set_axis(axis, labels)
420420

421-
def _update_inplace(self, result, **kwargs):
422-
# we want to call the generic version and not the IndexOpsMixin
423-
return generic.NDFrame._update_inplace(self, result, **kwargs)
424-
425421
# ndarray compatibility
426422
@property
427423
def dtype(self) -> DtypeObj:
@@ -1800,7 +1796,7 @@ def unique(self):
18001796
result = super().unique()
18011797
return result
18021798

1803-
def drop_duplicates(self, keep="first", inplace=False) -> "Series":
1799+
def drop_duplicates(self, keep="first", inplace=False) -> Optional["Series"]:
18041800
"""
18051801
Return Series with duplicate values removed.
18061802
@@ -1875,7 +1871,13 @@ def drop_duplicates(self, keep="first", inplace=False) -> "Series":
18751871
5 hippo
18761872
Name: animal, dtype: object
18771873
"""
1878-
return super().drop_duplicates(keep=keep, inplace=inplace)
1874+
inplace = validate_bool_kwarg(inplace, "inplace")
1875+
result = super().drop_duplicates(keep=keep)
1876+
if inplace:
1877+
self._update_inplace(result)
1878+
return None
1879+
else:
1880+
return result
18791881

18801882
def duplicated(self, keep="first") -> "Series":
18811883
"""

0 commit comments

Comments
 (0)