diff options
author | Serhiy Storchaka <storchaka@gmail.com> | 2021-06-12 12:15:17 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-12 12:15:17 (GMT) |
commit | 9f1c5f6e8af6ba3f659b2aea1e221ac9695828ba (patch) | |
tree | 178272613398d4b75696f439134094b135a08f2a | |
parent | 4a42cebf6dd769e2fa4e234a9e91093b3ad1cb63 (diff) | |
download | cpython-9f1c5f6e8af6ba3f659b2aea1e221ac9695828ba.zip cpython-9f1c5f6e8af6ba3f659b2aea1e221ac9695828ba.tar.gz cpython-9f1c5f6e8af6ba3f659b2aea1e221ac9695828ba.tar.bz2 |
bpo-43475: Fix the Python implementation of hash of Decimal NaN (GH-26679)
-rw-r--r-- | Doc/library/stdtypes.rst | 2 | ||||
-rw-r--r-- | Lib/_pydecimal.py | 2 | ||||
-rw-r--r-- | Lib/test/test_decimal.py | 23 | ||||
-rw-r--r-- | Lib/test/test_float.py | 19 |
4 files changed, 36 insertions, 10 deletions
diff --git a/Doc/library/stdtypes.rst b/Doc/library/stdtypes.rst index e34a888..3b2ff80 100644 --- a/Doc/library/stdtypes.rst +++ b/Doc/library/stdtypes.rst @@ -739,7 +739,7 @@ number, :class:`float`, or :class:`complex`:: """Compute the hash of a float x.""" if math.isnan(x): - return super().__hash__() + return object.__hash__(x) elif math.isinf(x): return sys.hash_info.inf if x > 0 else -sys.hash_info.inf else: diff --git a/Lib/_pydecimal.py b/Lib/_pydecimal.py index ff23322..3d6cece 100644 --- a/Lib/_pydecimal.py +++ b/Lib/_pydecimal.py @@ -951,7 +951,7 @@ class Decimal(object): if self.is_snan(): raise TypeError('Cannot hash a signaling NaN value.') elif self.is_nan(): - return super().__hash__() + return object.__hash__(self) else: if self._sign: return -_PyHASH_INF diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py index 179a9ea..058829b 100644 --- a/Lib/test/test_decimal.py +++ b/Lib/test/test_decimal.py @@ -1814,13 +1814,7 @@ class UsabilityTest(unittest.TestCase): # check that hash(d) == hash(int(d)) for integral values for value in test_values: - self.assertEqual(hashit(value), hashit(int(value))) - - #the same hash that to an int - self.assertEqual(hashit(Decimal(23)), hashit(23)) - self.assertRaises(TypeError, hash, Decimal('sNaN')) - self.assertTrue(hashit(Decimal('Inf'))) - self.assertTrue(hashit(Decimal('-Inf'))) + self.assertEqual(hashit(value), hash(int(value))) # check that the hashes of a Decimal float match when they # represent exactly the same values @@ -1829,7 +1823,7 @@ class UsabilityTest(unittest.TestCase): for s in test_strings: f = float(s) d = Decimal(s) - self.assertEqual(hashit(f), hashit(d)) + self.assertEqual(hashit(d), hash(f)) with localcontext() as c: # check that the value of the hash doesn't depend on the @@ -1850,6 +1844,19 @@ class UsabilityTest(unittest.TestCase): x = 1100 ** 1248 self.assertEqual(hashit(Decimal(x)), hashit(x)) + def test_hash_method_nan(self): + Decimal = self.decimal.Decimal + self.assertRaises(TypeError, hash, Decimal('sNaN')) + value = Decimal('NaN') + self.assertEqual(hash(value), object.__hash__(value)) + class H: + def __hash__(self): + return 42 + class D(Decimal, H): + pass + value = D('NaN') + self.assertEqual(hash(value), object.__hash__(value)) + def test_min_and_max_methods(self): Decimal = self.decimal.Decimal diff --git a/Lib/test/test_float.py b/Lib/test/test_float.py index ff4f387..f0ed40f 100644 --- a/Lib/test/test_float.py +++ b/Lib/test/test_float.py @@ -564,6 +564,25 @@ class GeneralFloatCases(unittest.TestCase): #self.assertTrue(0.0 < pow_op(2.0, -1047) < 1e-315) #self.assertTrue(0.0 > pow_op(-2.0, -1047) > -1e-315) + def test_hash(self): + for x in range(-30, 30): + self.assertEqual(hash(float(x)), hash(x)) + self.assertEqual(hash(float(sys.float_info.max)), + hash(int(sys.float_info.max))) + self.assertEqual(hash(float('inf')), sys.hash_info.inf) + self.assertEqual(hash(float('-inf')), -sys.hash_info.inf) + + def test_hash_nan(self): + value = float('nan') + self.assertEqual(hash(value), object.__hash__(value)) + class H: + def __hash__(self): + return 42 + class F(float, H): + pass + value = F('nan') + self.assertEqual(hash(value), object.__hash__(value)) + @requires_setformat class FormatFunctionsTestCase(unittest.TestCase): |