Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 9f1c5f6

Browse filesBrowse files
bpo-43475: Fix the Python implementation of hash of Decimal NaN (GH-26679)
1 parent 4a42ceb commit 9f1c5f6
Copy full SHA for 9f1c5f6

File tree

Expand file treeCollapse file tree

4 files changed

+36
-10
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+36
-10
lines changed

‎Doc/library/stdtypes.rst

Copy file name to clipboardExpand all lines: Doc/library/stdtypes.rst
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ number, :class:`float`, or :class:`complex`::
739739
"""Compute the hash of a float x."""
740740

741741
if math.isnan(x):
742-
return super().__hash__()
742+
return object.__hash__(x)
743743
elif math.isinf(x):
744744
return sys.hash_info.inf if x > 0 else -sys.hash_info.inf
745745
else:

‎Lib/_pydecimal.py

Copy file name to clipboardExpand all lines: Lib/_pydecimal.py
+1-1Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,7 @@ def __hash__(self):
951951
if self.is_snan():
952952
raise TypeError('Cannot hash a signaling NaN value.')
953953
elif self.is_nan():
954-
return super().__hash__()
954+
return object.__hash__(self)
955955
else:
956956
if self._sign:
957957
return -_PyHASH_INF

‎Lib/test/test_decimal.py

Copy file name to clipboardExpand all lines: Lib/test/test_decimal.py
+15-8Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1814,13 +1814,7 @@ def hashit(d):
18141814

18151815
# check that hash(d) == hash(int(d)) for integral values
18161816
for value in test_values:
1817-
self.assertEqual(hashit(value), hashit(int(value)))
1818-
1819-
#the same hash that to an int
1820-
self.assertEqual(hashit(Decimal(23)), hashit(23))
1821-
self.assertRaises(TypeError, hash, Decimal('sNaN'))
1822-
self.assertTrue(hashit(Decimal('Inf')))
1823-
self.assertTrue(hashit(Decimal('-Inf')))
1817+
self.assertEqual(hashit(value), hash(int(value)))
18241818

18251819
# check that the hashes of a Decimal float match when they
18261820
# represent exactly the same values
@@ -1829,7 +1823,7 @@ def hashit(d):
18291823
for s in test_strings:
18301824
f = float(s)
18311825
d = Decimal(s)
1832-
self.assertEqual(hashit(f), hashit(d))
1826+
self.assertEqual(hashit(d), hash(f))
18331827

18341828
with localcontext() as c:
18351829
# check that the value of the hash doesn't depend on the
@@ -1850,6 +1844,19 @@ def hashit(d):
18501844
x = 1100 ** 1248
18511845
self.assertEqual(hashit(Decimal(x)), hashit(x))
18521846

1847+
def test_hash_method_nan(self):
1848+
Decimal = self.decimal.Decimal
1849+
self.assertRaises(TypeError, hash, Decimal('sNaN'))
1850+
value = Decimal('NaN')
1851+
self.assertEqual(hash(value), object.__hash__(value))
1852+
class H:
1853+
def __hash__(self):
1854+
return 42
1855+
class D(Decimal, H):
1856+
pass
1857+
value = D('NaN')
1858+
self.assertEqual(hash(value), object.__hash__(value))
1859+
18531860
def test_min_and_max_methods(self):
18541861
Decimal = self.decimal.Decimal
18551862

‎Lib/test/test_float.py

Copy file name to clipboardExpand all lines: Lib/test/test_float.py
+19Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -564,6 +564,25 @@ def test_float_pow(self):
564564
#self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315)
565565
#self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315)
566566

567+
def test_hash(self):
568+
for x in range(-30, 30):
569+
self.assertEqual(hash(float(x)), hash(x))
570+
self.assertEqual(hash(float(sys.float_info.max)),
571+
hash(int(sys.float_info.max)))
572+
self.assertEqual(hash(float('inf')), sys.hash_info.inf)
573+
self.assertEqual(hash(float('-inf')), -sys.hash_info.inf)
574+
575+
def test_hash_nan(self):
576+
value = float('nan')
577+
self.assertEqual(hash(value), object.__hash__(value))
578+
class H:
579+
def __hash__(self):
580+
return 42
581+
class F(float, H):
582+
pass
583+
value = F('nan')
584+
self.assertEqual(hash(value), object.__hash__(value))
585+
567586

568587
@requires_setformat
569588
class FormatFunctionsTestCase(unittest.TestCase):

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.