summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rwxr-xr-xLib/cgi.py12
-rw-r--r--Lib/decimal.py15
-rw-r--r--Lib/test/test_decimal.py32
3 files changed, 48 insertions, 11 deletions
diff --git a/Lib/cgi.py b/Lib/cgi.py
index 7b457cc..cb92cfc 100755
--- a/Lib/cgi.py
+++ b/Lib/cgi.py
@@ -604,23 +604,21 @@ class FieldStorage:
"""Dictionary style keys() method."""
if self.list is None:
raise TypeError("not indexable")
- keys = []
- for item in self.list:
- if item.name not in keys: keys.append(item.name)
- return keys
+ return list(set(item.name for item in self.list))
def __contains__(self, key):
"""Dictionary style __contains__ method."""
if self.list is None:
raise TypeError("not indexable")
- for item in self.list:
- if item.name == key: return True
- return False
+ return any(item.name == key for item in self.list)
def __len__(self):
"""Dictionary style len(x) support."""
return len(self.keys())
+ def __nonzero__(self):
+ return bool(self.list)
+
def read_urlencoded(self):
"""Internal: read data in query string format."""
qs = self.fp.read(self.length)
diff --git a/Lib/decimal.py b/Lib/decimal.py
index d7bd127..ffe6e9e 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -786,10 +786,17 @@ class Decimal(object):
if self._isnan():
raise TypeError('Cannot hash a NaN value.')
return hash(str(self))
- i = int(self)
- if self == Decimal(i):
- return hash(i)
- assert self.__bool__() # '-0' handled by integer case
+ if not self:
+ return 0
+ if self._isinteger():
+ op = _WorkRep(self.to_integral_value())
+ # to make computation feasible for Decimals with large
+ # exponent, we use the fact that hash(n) == hash(m) for
+ # any two nonzero integers n and m such that (i) n and m
+ # have the same sign, and (ii) n is congruent to m modulo
+ # 2**64-1. So we can replace hash((-1)**s*c*10**e) with
+ # hash((-1)**s*c*pow(10, e, 2**64-1).
+ return hash((-1)**op.sign*op.int*pow(10, op.exp, 2**64-1))
return hash(str(self.normalize()))
def as_tuple(self):
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index 41d1dd5..513ba16 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -901,6 +901,38 @@ class DecimalUsabilityTest(unittest.TestCase):
def test_hash_method(self):
#just that it's hashable
hash(Decimal(23))
+
+ test_values = [Decimal(sign*(2**m + n))
+ for m in [0, 14, 15, 16, 17, 30, 31,
+ 32, 33, 62, 63, 64, 65, 66]
+ for n in range(-10, 10)
+ for sign in [-1, 1]]
+ test_values.extend([
+ Decimal("-0"), # zeros
+ Decimal("0.00"),
+ Decimal("-0.000"),
+ Decimal("0E10"),
+ Decimal("-0E12"),
+ Decimal("10.0"), # negative exponent
+ Decimal("-23.00000"),
+ Decimal("1230E100"), # positive exponent
+ Decimal("-4.5678E50"),
+ # a value for which hash(n) != hash(n % (2**64-1))
+ # in Python pre-2.6
+ Decimal(2**64 + 2**32 - 1),
+ # selection of values which fail with the old (before
+ # version 2.6) long.__hash__
+ Decimal("1.634E100"),
+ Decimal("90.697E100"),
+ Decimal("188.83E100"),
+ Decimal("1652.9E100"),
+ Decimal("56531E100"),
+ ])
+
+ # check that hash(d) == hash(int(d)) for integral values
+ for value in test_values:
+ self.assertEqual(hash(value), hash(int(value)))
+
#the same hash that to an int
self.assertEqual(hash(Decimal(23)), hash(23))
self.assertRaises(TypeError, hash, Decimal('NaN'))