diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index f7661a7686..1decce0216 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -47,7 +47,8 @@ class BaseDatabaseWrapper(object): def __ne__(self, other): return not self == other - __hash__ = object.__hash__ + def __hash__(self): + return hash(self.alias) def _commit(self): if self.connection is not None: diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 94abfd784c..67d2531ad4 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -135,7 +135,8 @@ class Field(object): return self.creation_counter < other.creation_counter return NotImplemented - __hash__ = object.__hash__ + def __hash__(self): + return hash(self.creation_counter) def __deepcopy__(self, memodict): # We don't have to deepcopy very much here, since most things are not diff --git a/django/db/models/fields/files.py b/django/db/models/fields/files.py index e0cc27a081..e631f177e9 100644 --- a/django/db/models/fields/files.py +++ b/django/db/models/fields/files.py @@ -30,7 +30,6 @@ class FieldFile(File): return not self.__eq__(other) def __hash__(self): - # Required because we defined a custom __eq__. return hash(self.name) # The standard File contains most of the necessary properties, but diff --git a/django/dispatch/saferef.py b/django/dispatch/saferef.py index 7423669c96..c7731d41fe 100644 --- a/django/dispatch/saferef.py +++ b/django/dispatch/saferef.py @@ -152,7 +152,8 @@ class BoundMethodWeakref(object): __repr__ = __str__ - __hash__ = object.__hash__ + def __hash__(self): + return hash(self.key) def __bool__( self ): """Whether we are still a valid reference""" diff --git a/django/test/html.py b/django/test/html.py index 2f6e4c9481..cda9dfab27 100644 --- a/django/test/html.py +++ b/django/test/html.py @@ -85,7 +85,8 @@ class Element(object): return False return True - __hash__ = object.__hash__ + def __hash__(self): + return hash((self.name,) + tuple(a for a in self.attributes)) def __ne__(self, element): return not self.__eq__(element) diff --git a/django/utils/functional.py b/django/utils/functional.py index 505931e158..1dcbd55664 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -150,7 +150,8 @@ def lazy(func, *resultclasses): other = other.__cast() return self.__cast() < other - __hash__ = object.__hash__ + def __hash__(self): + return hash(self.__cast()) def __mod__(self, rhs): if self._delegate_bytes and not six.PY3: diff --git a/tests/regressiontests/backends/tests.py b/tests/regressiontests/backends/tests.py index 1188da56ba..b92d3b9231 100644 --- a/tests/regressiontests/backends/tests.py +++ b/tests/regressiontests/backends/tests.py @@ -581,25 +581,27 @@ class ThreadTests(TestCase): Ensure that the connections are different for each thread. Refs #17258. """ - connections_set = set() + # Map connections by id because connections with identical aliases + # have the same hash. + connections_dict = {} for conn in connections.all(): - connections_set.add(conn) + connections_dict[id(conn)] = conn def runner(): from django.db import connections for conn in connections.all(): # Allow thread sharing so the connection can be closed by the # main thread. conn.allow_thread_sharing = True - connections_set.add(conn) + connections_dict[id(conn)] = conn for x in range(2): t = threading.Thread(target=runner) t.start() t.join() - self.assertEqual(len(connections_set), 6) + self.assertEqual(len(connections_dict), 6) # Finish by closing the connections opened by the other threads (the # connection opened in the main thread will automatically be closed on # teardown). - for conn in connections_set: + for conn in connections_dict.values(): if conn != connection: conn.close()