diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py index 958982bdae9..b77455e6e1d 100644 --- a/django/db/backends/__init__.py +++ b/django/db/backends/__init__.py @@ -51,7 +51,8 @@ class BaseDatabaseWrapper(object): def __ne__(self, other): return not self == other - __hash__ = object.__hash__ + def __hash__(self): + return hash(self.alias) def get_connection_params(self): raise NotImplementedError diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index 279c712a983..2702876397d 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 e0cc27a081d..e631f177e92 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 7423669c968..c7731d41feb 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 2f6e4c94817..cda9dfab270 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 51001ea6559..69a32b101a1 100644 --- a/django/utils/functional.py +++ b/django/utils/functional.py @@ -152,7 +152,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 0e1700b36e3..b0413b1ebc2 100644 --- a/tests/regressiontests/backends/tests.py +++ b/tests/regressiontests/backends/tests.py @@ -576,9 +576,11 @@ class ThreadTests(TestCase): different for each thread. Refs #17258. """ - connections_set = set() + # Map connections by id because connections with identical aliases + # have the same hash. + connections_dict = {} connection.cursor() - connections_set.add(connection) + connections_dict[id(connection)] = connection def runner(): # Passing django.db.connection between threads doesn't work while # connections[DEFAULT_DB_ALIAS] does. @@ -588,19 +590,19 @@ class ThreadTests(TestCase): # main thread. connection.allow_thread_sharing = True connection.cursor() - connections_set.add(connection) + connections_dict[id(connection)] = connection for x in range(2): t = threading.Thread(target=runner) t.start() t.join() # Check that each created connection got different inner connection. self.assertEqual( - len(set([conn.connection for conn in connections_set])), + len(set(conn.connection for conn in connections_dict.values())), 3) # 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 is not connection: conn.close() @@ -609,25 +611,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 is not connection: conn.close()