Repository: pydantic/pydantic

Issue:
`pydantic.color.Color` is not hashable in 1.10.0 release
### Initial Checks

- [X] I have searched GitHub for a duplicate issue and I'm sure this is something new
- [X] I have searched Google & StackOverflow for a solution and couldn't find anything
- [X] I have read and followed [the docs](https://pydantic-docs.helpmanual.io) and still think this is a bug
- [X] I am confident that the issue is with pydantic  (not my code, or another library in the ecosystem like [FastAPI](https://fastapi.tiangolo.com) or [mypy](https://mypy.readthedocs.io/en/stable))


### Description

In pydantic `1.9.2` (and earlier), the Color class was Hashable. in release 1.10.0 it is not hashable that broke usage color as an argument to function decorated with `@lru_cache` from std lib. (https://github.com/napari/napari/issues/4995) 

A I do not see public method for mutate such object IO thin that it is deprecation. 

### Example Code

pydantic 1.9.2
```Python

In [1]: from pydantic.color import Color                                                     

In [2]: a = Color((0,0,0))                                                                   

In [3]: hash(a)                                                                              
Out[3]: 8771047785283
```

pydantic 1.10.0
```python
In [1]: from pydantic.color import Color                                                     

In [2]: a = Color((0,0,0))                                                                   

In [3]: hash(a)                                                                              
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-3-57b555d30865> in <module>
----> 1 hash(a)

TypeError: unhashable type: 'Color'
```
```


### Python, Pydantic & OS Version

```Text
pydantic 1.9.2 vs pydantic 1.10.0 tested on ubuntu and macos m1.
```


### Affected Components

- [X] [Compatibility between releases](https://pydantic-docs.helpmanual.io/changelog/)
- [ ] [Data validation/parsing](https://pydantic-docs.helpmanual.io/usage/models/#basic-model-usage)
- [ ] [Data serialization](https://pydantic-docs.helpmanual.io/usage/exporting_models/) - `.dict()` and `.json()`
- [ ] [JSON Schema](https://pydantic-docs.helpmanual.io/usage/schema/)
- [ ] [Dataclasses](https://pydantic-docs.helpmanual.io/usage/dataclasses/)
- [ ] [Model Config](https://pydantic-docs.helpmanual.io/usage/model_config/)
- [x] [Field Types](https://pydantic-docs.helpmanual.io/usage/types/) - adding or changing a particular data type
- [ ] [Function validation decorator](https://pydantic-docs.helpmanual.io/usage/validation_decorator/)
- [ ] [Generic Models](https://pydantic-docs.helpmanual.io/usage/models/#generic-models)
- [X] [Other Model behaviour](https://pydantic-docs.helpmanual.io/usage/models/) - `construct()`, pickling, private attributes, ORM mode
- [ ] [Settings Management](https://pydantic-docs.helpmanual.io/usage/settings/)
- [ ] [Plugins](https://pydantic-docs.helpmanual.io/) and integration with other tools - mypy, FastAPI, python-devtools, Hypothesis, VS Code, PyCharm, etc.


Discussion:
Thanks so much for reporting, I've added `napari` to #4359.

Confirmed. Seems this was an unexpected side effect of #3646 I didn't know that adding `__eq__` brakes hashing.

PR welcome to fix this, otherwise I'll do it soon.
I just found it here (second paragraph): [`https://docs.python.org/3/reference/datamodel.html#object.__hash__`](https://docs.python.org/3/reference/datamodel.html#object.__hash__), but also do not know earlier. 

Resolving patch:
diff --git a/pydantic/color.py b/pydantic/color.py
--- a/pydantic/color.py
+++ b/pydantic/color.py
@@ -201,6 +201,9 @@ def __repr_args__(self) -> 'ReprArgs':
     def __eq__(self, other: Any) -> bool:
         return isinstance(other, Color) and self.as_rgb_tuple() == other.as_rgb_tuple()
 
+    def __hash__(self) -> int:
+        return hash(self.as_rgb_tuple())
+
 
 def parse_tuple(value: Tuple[Any, ...]) -> RGBA:
     """


Test patch:
diff --git a/tests/test_color.py b/tests/test_color.py
--- a/tests/test_color.py
+++ b/tests/test_color.py
@@ -193,3 +193,9 @@ def test_eq():
 
     assert Color('red') == Color((255, 0, 0))
     assert Color('red') != Color((0, 0, 255))
+
+
+def test_color_hashable():
+    assert hash(Color('red')) != hash(Color('blue'))
+    assert hash(Color('red')) == hash(Color((255, 0, 0)))
+    assert hash(Color('red')) != hash(Color((255, 0, 0, 0.5)))