diff --git a/RELEASE.rst b/RELEASE.rst index 307986ab81681..072f40d927108 100644 --- a/RELEASE.rst +++ b/RELEASE.rst @@ -220,6 +220,7 @@ pandas 0.11.1 - Groupby transform with item-by-item not upcasting correctly (GH3740_) - Incorrectly read a HDFStore multi-index Frame witha column specification (GH3748_) - ``read_html`` now correctly skips tests (GH3741_) + - PandasObjects raise TypeError when trying to hash (GH3882_) - Fix incorrect arguments passed to concat that are not list-like (e.g. concat(df1,df2)) (GH3481_) - Correctly parse when passed the ``dtype=str`` (or other variable-len string dtypes) in ``read_csv`` (GH3795_) diff --git a/pandas/core/generic.py b/pandas/core/generic.py index 0d2612d7aed7a..3a3ce49d50c5a 100644 --- a/pandas/core/generic.py +++ b/pandas/core/generic.py @@ -31,6 +31,11 @@ def save(self, path): def load(cls, path): return com.load(path) + def __hash__(self): + raise TypeError('{0!r} objects are mutable, thus they cannot be' + ' hashed'.format(self.__class__.__name__)) + + #---------------------------------------------------------------------- # Axis name business diff --git a/pandas/core/series.py b/pandas/core/series.py index 3a7a7d0f49b66..2621c64afc205 100644 --- a/pandas/core/series.py +++ b/pandas/core/series.py @@ -527,9 +527,6 @@ def _constructor(self): def _can_hold_na(self): return not is_integer_dtype(self.dtype) - def __hash__(self): - raise TypeError('unhashable type') - _index = None index = lib.SeriesIndex() diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index 2c6d3b221c6ff..1e8fa91548145 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -3109,6 +3109,11 @@ def test_constructor_for_list_with_dtypes(self): expected.sort() assert_series_equal(result, expected) + def test_not_hashable(self): + df = pd.DataFrame([1]) + self.assertRaises(TypeError, hash, df) + self.assertRaises(TypeError, hash, self.empty) + def test_timedeltas(self): df = DataFrame(dict(A = Series(date_range('2012-1-1', periods=3, freq='D')), diff --git a/pandas/tests/test_panel.py b/pandas/tests/test_panel.py index 58b7ac272401f..380604b0de32e 100644 --- a/pandas/tests/test_panel.py +++ b/pandas/tests/test_panel.py @@ -46,6 +46,12 @@ def test_cumsum(self): cumsum = self.panel.cumsum() assert_frame_equal(cumsum['ItemA'], self.panel['ItemA'].cumsum()) + def not_hashable(self): + c_empty = Panel() + c = Panel(pd.Panel([[[1]]])) + self.assertRaises(TypeError, hash, c_empty) + self.assertRaises(TypeError, hash, c) + class SafeForLongAndSparse(object): _multiprocess_can_split_ = True diff --git a/pandas/tests/test_panel4d.py b/pandas/tests/test_panel4d.py index a2e08bc744ab0..9c3a66c32c501 100644 --- a/pandas/tests/test_panel4d.py +++ b/pandas/tests/test_panel4d.py @@ -785,6 +785,11 @@ def test_reindex(self): major=self.panel4d.major_axis, copy=False) self.assert_(result is self.panel4d) + def test_not_hashable(self): + p4D_empty = Panel4D() + self.assertRaises(TypeError, hash, p4D_empty) + self.assertRaises(TypeError, hash, self.panel4d) + def test_reindex_like(self): # reindex_like smaller = self.panel4d.reindex(labels=self.panel4d.labels[:-1], diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 88990bdde98b8..d04da38f0e526 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -579,6 +579,12 @@ def test_setindex(self): def test_array_finalize(self): pass + def test_not_hashable(self): + s_empty = Series() + s = Series([1]) + self.assertRaises(TypeError, hash, s_empty) + self.assertRaises(TypeError, hash, s) + def test_fromValue(self): nans = Series(np.NaN, index=self.ts.index)