Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/source/release.rst
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,8 @@ API Changes
('mostly immutable')
- ``levels``, ``labels`` and ``names`` are validated upon setting and are
either copied or shallow-copied.
- inplace setting of ``levels`` or ``labels`` now correctly invalidates the
cached properties. (:issue:`5238`).
- ``__deepcopy__`` now returns a shallow copy (currently: a view) of the
data - allowing metadata changes.
- ``MultiIndex.astype()`` now only allows ``np.object_``-like dtypes and
Expand Down
33 changes: 23 additions & 10 deletions pandas/core/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,16 +48,6 @@ def __repr__(self):
"""
return str(self)

def _local_dir(self):
""" provide addtional __dir__ for this object """
return []

def __dir__(self):
"""
Provide method name lookup and completion
Only provide 'public' methods
"""
return list(sorted(list(set(dir(type(self)) + self._local_dir()))))

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

def _local_dir(self):
""" provide addtional __dir__ for this object """
return []

def __dir__(self):
"""
Provide method name lookup and completion
Only provide 'public' methods
"""
return list(sorted(list(set(dir(type(self)) + self._local_dir()))))

def _reset_cache(self, key=None):
"""
Reset cached properties. If ``key`` is passed, only clears that key.
"""
if getattr(self, '_cache', None) is None:
return
if key is None:
self._cache.clear()
else:
self._cache.pop(key, None)


class FrozenList(PandasObject, list):
"""
Container that doesn't allow setting item *but*
Expand Down
3 changes: 3 additions & 0 deletions pandas/core/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -1929,7 +1929,9 @@ def _set_levels(self, levels, copy=False, validate=True,
self._levels = levels
if any(names):
self._set_names(names)

self._tuples = None
self._reset_cache()

if verify_integrity:
self._verify_integrity()
Expand Down Expand Up @@ -1981,6 +1983,7 @@ def _set_labels(self, labels, copy=False, validate=True,
self._labels = FrozenList(_ensure_frozen(labs, copy=copy)._shallow_copy()
for labs in labels)
self._tuples = None
self._reset_cache()

if verify_integrity:
self._verify_integrity()
Expand Down
10 changes: 10 additions & 0 deletions pandas/tests/test_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -2462,6 +2462,16 @@ def test_isnull_behavior(self):
with tm.assertRaises(NotImplementedError):
pd.isnull(self.index)

def test_level_setting_resets_attributes(self):
ind = MultiIndex.from_arrays([
['A', 'A', 'B', 'B', 'B'],
[1, 2, 1, 2, 3]])
assert ind.is_monotonic
ind.set_levels([['A', 'B', 'A', 'A', 'B'], [2, 1, 3, -2, 5]],
inplace=True)
# if this fails, probably didn't reset the cache correctly.
assert not ind.is_monotonic


def test_get_combined_index():
from pandas.core.index import _get_combined_index
Expand Down