Skip to content

Commit 74d42a5

Browse files
committed
CLN: Add _reset_cache method to PandasObject
1 parent f70a6e2 commit 74d42a5

File tree

4 files changed

+38
-10
lines changed

4 files changed

+38
-10
lines changed

doc/source/release.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,8 @@ API Changes
257257
('mostly immutable')
258258
- ``levels``, ``labels`` and ``names`` are validated upon setting and are
259259
either copied or shallow-copied.
260+
- inplace setting of ``levels`` or ``labels`` now correctly invalidates the
261+
cached properties. (:issue:`5238`).
260262
- ``__deepcopy__`` now returns a shallow copy (currently: a view) of the
261263
data - allowing metadata changes.
262264
- ``MultiIndex.astype()`` now only allows ``np.object_``-like dtypes and

pandas/core/base.py

Lines changed: 23 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -48,16 +48,6 @@ def __repr__(self):
4848
"""
4949
return str(self)
5050

51-
def _local_dir(self):
52-
""" provide addtional __dir__ for this object """
53-
return []
54-
55-
def __dir__(self):
56-
"""
57-
Provide method name lookup and completion
58-
Only provide 'public' methods
59-
"""
60-
return list(sorted(list(set(dir(type(self)) + self._local_dir()))))
6151

6252
class PandasObject(StringMixin):
6353
"""baseclass for various pandas objects"""
@@ -77,6 +67,29 @@ def __unicode__(self):
7767
# Should be overwritten by base classes
7868
return object.__repr__(self)
7969

70+
def _local_dir(self):
71+
""" provide addtional __dir__ for this object """
72+
return []
73+
74+
def __dir__(self):
75+
"""
76+
Provide method name lookup and completion
77+
Only provide 'public' methods
78+
"""
79+
return list(sorted(list(set(dir(type(self)) + self._local_dir()))))
80+
81+
def _reset_cache(self, key=None):
82+
"""
83+
Reset cached properties. If ``key`` is passed, only clears that key.
84+
"""
85+
if getattr(self, '_cache', None) is None:
86+
return
87+
if key is None:
88+
self._cache.clear()
89+
else:
90+
self._cache.pop(key, None)
91+
92+
8093
class FrozenList(PandasObject, list):
8194
"""
8295
Container that doesn't allow setting item *but*

pandas/core/index.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1929,7 +1929,9 @@ def _set_levels(self, levels, copy=False, validate=True,
19291929
self._levels = levels
19301930
if any(names):
19311931
self._set_names(names)
1932+
19321933
self._tuples = None
1934+
self._reset_cache()
19331935

19341936
if verify_integrity:
19351937
self._verify_integrity()
@@ -1981,6 +1983,7 @@ def _set_labels(self, labels, copy=False, validate=True,
19811983
self._labels = FrozenList(_ensure_frozen(labs, copy=copy)._shallow_copy()
19821984
for labs in labels)
19831985
self._tuples = None
1986+
self._reset_cache()
19841987

19851988
if verify_integrity:
19861989
self._verify_integrity()

pandas/tests/test_index.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2462,6 +2462,16 @@ def test_isnull_behavior(self):
24622462
with tm.assertRaises(NotImplementedError):
24632463
pd.isnull(self.index)
24642464

2465+
def test_level_setting_resets_attributes(self):
2466+
ind = MultiIndex.from_arrays([
2467+
['A', 'A', 'B', 'B', 'B'],
2468+
[1, 2, 1, 2, 3]])
2469+
assert ind.is_monotonic
2470+
ind.set_levels([['A', 'B', 'A', 'A', 'B'], [2, 1, 3, -2, 5]],
2471+
inplace=True)
2472+
# if this fails, probably didn't reset the cache correctly.
2473+
assert not ind.is_monotonic
2474+
24652475

24662476
def test_get_combined_index():
24672477
from pandas.core.index import _get_combined_index

0 commit comments

Comments
 (0)