TYP Series and DataFrame currently type-check as hashable
State: closed

- [ ] closes #40013 
- [ ] tests added / passed
- [ ] Ensure all linting tests pass, see [here](https://pandas.pydata.org/pandas-docs/dev/development/contributing.html#code-standards) for how to run them
- [ ] whatsnew entry


Labels:
name: Typing
description: type annotations, mypy/pyright type checking

Comments:
@MarcoGorelli does this also take care of #40013?
Thanks @mzeitlin11 - indeed, it looks like they're duplicates, I'll close the new one I'd opened
@jbrockmendel @jreback I've updated to just use `__hash__: None`, which is what they do in typeshed (https://github.com/python/typeshed/blob/3fa5988a2ac57cf8ce56e2de171a62b39952f96c/stdlib/builtins.pyi#L602)

The builtin error message will now be shown instead, so I've updated a few tests accordingly. Now, this is what'll be shown:
```python
In [1]: hash(pd.Series([1, 2, 3]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-1f0c9bc1928b> in <module>
----> 1 hash(pd.Series([1, 2, 3]))

TypeError: unhashable type: 'Series'
```

instead of

```python
In [1]: hash(pd.Series([1, 2, 3]))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-1-1f0c9bc1928b> in <module>
----> 1 hash(pd.Series([1, 2, 3]))

~/pandas-marco/pandas/core/generic.py in __hash__(self)
   1874 
   1875     def __hash__(self) -> int:
-> 1876         raise TypeError(
   1877             f"{repr(type(self).__name__)} objects are mutable, "
   1878             f"thus they cannot be hashed"

TypeError: 'Series' objects are mutable, thus they cannot be hashed
```
no objection here
ok this seems reasonable. can you add a release note about the changing error message & rebase. ping on green.
cool - @jreback done, green
@MarcoGorelli some comment and can  you rebase
> (or do we have tests and not check the message)?

They have tests, but it's only Series and DataFrame that had this custom error message ("'Series' objects are mutable, thus they cannot be hashed"), for EA and indexes it was already "unhashable type:" (however, they still type-checked as hashable)
This is more than a message change because previously `isinstance(x, collections.abc.Hashable)` would return `True` and now it will return `False`, right? (That said, the existing behavior is wrong, so IMO fixing this sooner rather than later would be helpful ... I currently have an awkward workaround to deal with it in a way that mypy understands).
> This is more than a message change because previously `isinstance(x, collections.abc.Hashable)` would return `True` and now it will return `False`, right? 

Indeed, you are correct (I wasn't aware that this would affect that):

```python
# here
In [4]: isinstance(Series([1,2,3]), collections.abc.Hashable)
Out[4]: False

#master
In [2]: isinstance(Series([1,2,3]), collections.abc.Hashable)
Out[2]: True
```

> IMO fixing this sooner rather than later would be helpful

Agreed 
@MarcoGorelli can you merge master to resolve conflicts
@MarcoGorelli if you can merge master 
mypy will fail.

I think undo all the changes to pandas/core/frame.py

and just do

```
        if subset is None:
            subset = cast(Sequence[Hashable], self.columns)
        elif (
```

could maybe add link to https://github.com/pandas-dev/pandas/issues/28770 as related.
> and just do
> 
> ```
>         if subset is None:
>             subset = cast(Sequence[Hashable], self.columns)
>         elif (
> ```

or undo all the changes to frame.py and could simply ignore `pandas/core/frame.py:6183: error: Incompatible types in assignment (expression has type "Index", variable has type "Union[Hashable, Sequence[Hashable], None]")  [assignment]`

and we can remove the ignore once  #28770 is fixed (for all pandas objects)
thanks @MarcoGorelli 
@meeseeksdev backport 1.3.x
Something went wrong ... Please have  a look at my logs.