Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

[1.5.x] Fixed #19634 -- Added proper __hash__ methods.

Classes overriding __eq__ need a __hash__ such that equal objects have
the same hash.

Thanks akaariai for the report and regebro for the patch.

Backport of e76147a from master.
  • Loading branch information...
commit 702d39921cb95883d3b7590eadd65b03f76d0f92 1 parent 1742fd0
@aaugustin aaugustin authored
View
3  django/db/backends/__init__.py
@@ -47,7 +47,8 @@ def __eq__(self, other):
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:
View
3  django/db/models/fields/__init__.py
@@ -135,7 +135,8 @@ def __lt__(self, other):
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
View
1  django/db/models/fields/files.py
@@ -30,7 +30,6 @@ def __ne__(self, other):
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
View
3  django/dispatch/saferef.py
@@ -152,7 +152,8 @@ def __str__(self):
__repr__ = __str__
- __hash__ = object.__hash__
+ def __hash__(self):
+ return hash(self.key)
def __bool__( self ):
"""Whether we are still a valid reference"""
View
3  django/test/html.py
@@ -85,7 +85,8 @@ def __eq__(self, element):
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)
View
3  django/utils/functional.py
@@ -150,7 +150,8 @@ def __lt__(self, other):
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:
View
12 tests/regressiontests/backends/tests.py
@@ -581,25 +581,27 @@ def test_connections_thread_local(self):
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()

0 comments on commit 702d399

Please sign in to comment.
Something went wrong with that request. Please try again.