summaryrefslogtreecommitdiffstats
path: root/Lib
diff options
context:
space:
mode:
Diffstat (limited to 'Lib')
-rw-r--r--Lib/collections.py5
-rw-r--r--Lib/decimal.py14
-rw-r--r--Lib/test/test_decimal.py17
-rw-r--r--Lib/test/test_pyexpat.py128
-rw-r--r--Lib/test/test_socket.py2
-rw-r--r--Lib/test/test_winreg.py45
6 files changed, 184 insertions, 27 deletions
diff --git a/Lib/collections.py b/Lib/collections.py
index 2f0d038..e1e9d11 100644
--- a/Lib/collections.py
+++ b/Lib/collections.py
@@ -34,7 +34,8 @@ def namedtuple(typename, field_names, verbose=False):
"""
- # Parse and validate the field names
+ # Parse and validate the field names. Validation serves two purposes,
+ # generating informative error messages and preventing template injection attacks.
if isinstance(field_names, str):
field_names = field_names.replace(',', ' ').split() # names separated by whitespace and/or commas
field_names = tuple(field_names)
@@ -129,7 +130,7 @@ if __name__ == '__main__':
'Point class with optimized _make() and _replace() without error-checking'
_make = classmethod(tuple.__new__)
def _replace(self, _map=map, **kwds):
- return self._make(_map(kwds.pop, ('x', 'y'), self))
+ return self._make(_map(kwds.get, ('x', 'y'), self))
print(Point(11, 22)._replace(x=100))
diff --git a/Lib/decimal.py b/Lib/decimal.py
index 54e8cb4..1f5ff12 100644
--- a/Lib/decimal.py
+++ b/Lib/decimal.py
@@ -809,8 +809,10 @@ class Decimal(_numbers.Real, _numbers.Inexact):
def __hash__(self):
"""x.__hash__() <==> hash(x)"""
# Decimal integers must hash the same as the ints
- # Non-integer decimals are normalized and hashed as strings
- # Normalization assures that hash(100E-1) == hash(10)
+ #
+ # The hash of a nonspecial noninteger Decimal must depend only
+ # on the value of that Decimal, and not on its representation.
+ # For example: hash(Decimal("100E-1")) == hash(Decimal("10")).
if self._is_special:
if self._isnan():
raise TypeError('Cannot hash a NaN value.')
@@ -826,7 +828,13 @@ class Decimal(_numbers.Real, _numbers.Inexact):
# 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()))
+ # The value of a nonzero nonspecial Decimal instance is
+ # faithfully represented by the triple consisting of its sign,
+ # its adjusted exponent, and its coefficient with trailing
+ # zeros removed.
+ return hash((self._sign,
+ self._exp+len(self._int),
+ self._int.rstrip('0')))
def as_tuple(self):
"""Represents the number as a triple tuple.
diff --git a/Lib/test/test_decimal.py b/Lib/test/test_decimal.py
index 3c64e64..0dd7f00 100644
--- a/Lib/test/test_decimal.py
+++ b/Lib/test/test_decimal.py
@@ -971,6 +971,23 @@ class DecimalUsabilityTest(unittest.TestCase):
self.assert_(hash(Decimal('Inf')))
self.assert_(hash(Decimal('-Inf')))
+ # check that the value of the hash doesn't depend on the
+ # current context (issue #1757)
+ c = getcontext()
+ old_precision = c.prec
+ x = Decimal("123456789.1")
+
+ c.prec = 6
+ h1 = hash(x)
+ c.prec = 10
+ h2 = hash(x)
+ c.prec = 16
+ h3 = hash(x)
+
+ self.assertEqual(h1, h2)
+ self.assertEqual(h1, h3)
+ c.prec = old_precision
+
def test_min_and_max_methods(self):
d1 = Decimal('15.32')
diff --git a/Lib/test/test_pyexpat.py b/Lib/test/test_pyexpat.py
index cb4e6eb..9fda72d 100644
--- a/Lib/test/test_pyexpat.py
+++ b/Lib/test/test_pyexpat.py
@@ -2,6 +2,7 @@
# handler, are obscure and unhelpful.
from io import BytesIO
+import sys
import unittest
import pyexpat
@@ -385,6 +386,130 @@ class sf1296433Test(unittest.TestCase):
self.assertRaises(Exception, parser.Parse, xml)
+class ChardataBufferTest(unittest.TestCase):
+ """
+ test setting of chardata buffer size
+ """
+
+ def test_1025_bytes(self):
+ self.assertEquals(self.small_buffer_test(1025), 2)
+
+ def test_1000_bytes(self):
+ self.assertEquals(self.small_buffer_test(1000), 1)
+
+ def test_wrong_size(self):
+ parser = expat.ParserCreate()
+ parser.buffer_text = 1
+ def f(size):
+ parser.buffer_size = size
+
+ self.assertRaises(ValueError, f, -1)
+ self.assertRaises(ValueError, f, 0)
+
+ def test_unchanged_size(self):
+ xml1 = ("<?xml version='1.0' encoding='iso8859'?><s>%s" % ('a' * 512))
+ xml2 = 'a'*512 + '</s>'
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = self.counting_handler
+ parser.buffer_size = 512
+ parser.buffer_text = 1
+
+ # Feed 512 bytes of character data: the handler should be called
+ # once.
+ self.n = 0
+ parser.Parse(xml1)
+ self.assertEquals(self.n, 1)
+
+ # Reassign to buffer_size, but assign the same size.
+ parser.buffer_size = parser.buffer_size
+ self.assertEquals(self.n, 1)
+
+ # Try parsing rest of the document
+ parser.Parse(xml2)
+ self.assertEquals(self.n, 2)
+
+
+ def test_disabling_buffer(self):
+ xml1 = "<?xml version='1.0' encoding='iso8859'?><a>%s" % ('a' * 512)
+ xml2 = ('b' * 1024)
+ xml3 = "%s</a>" % ('c' * 1024)
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = self.counting_handler
+ parser.buffer_text = 1
+ parser.buffer_size = 1024
+ self.assertEquals(parser.buffer_size, 1024)
+
+ # Parse one chunk of XML
+ self.n = 0
+ parser.Parse(xml1, 0)
+ self.assertEquals(parser.buffer_size, 1024)
+ self.assertEquals(self.n, 1)
+
+ # Turn off buffering and parse the next chunk.
+ parser.buffer_text = 0
+ self.assertFalse(parser.buffer_text)
+ self.assertEquals(parser.buffer_size, 1024)
+ for i in range(10):
+ parser.Parse(xml2, 0)
+ self.assertEquals(self.n, 11)
+
+ parser.buffer_text = 1
+ self.assertTrue(parser.buffer_text)
+ self.assertEquals(parser.buffer_size, 1024)
+ parser.Parse(xml3, 1)
+ self.assertEquals(self.n, 12)
+
+
+
+ def make_document(self, bytes):
+ return ("<?xml version='1.0'?><tag>" + bytes * 'a' + '</tag>')
+
+ def counting_handler(self, text):
+ self.n += 1
+
+ def small_buffer_test(self, buffer_len):
+ xml = "<?xml version='1.0' encoding='iso8859'?><s>%s</s>" % ('a' * buffer_len)
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = self.counting_handler
+ parser.buffer_size = 1024
+ parser.buffer_text = 1
+
+ self.n = 0
+ parser.Parse(xml)
+ return self.n
+
+ def test_change_size_1(self):
+ xml1 = "<?xml version='1.0' encoding='iso8859'?><a><s>%s" % ('a' * 1024)
+ xml2 = "aaa</s><s>%s</s></a>" % ('a' * 1025)
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = self.counting_handler
+ parser.buffer_text = 1
+ parser.buffer_size = 1024
+ self.assertEquals(parser.buffer_size, 1024)
+
+ self.n = 0
+ parser.Parse(xml1, 0)
+ parser.buffer_size *= 2
+ self.assertEquals(parser.buffer_size, 2048)
+ parser.Parse(xml2, 1)
+ self.assertEquals(self.n, 2)
+
+ def test_change_size_2(self):
+ xml1 = "<?xml version='1.0' encoding='iso8859'?><a>a<s>%s" % ('a' * 1023)
+ xml2 = "aaa</s><s>%s</s></a>" % ('a' * 1025)
+ parser = expat.ParserCreate()
+ parser.CharacterDataHandler = self.counting_handler
+ parser.buffer_text = 1
+ parser.buffer_size = 2048
+ self.assertEquals(parser.buffer_size, 2048)
+
+ self.n=0
+ parser.Parse(xml1, 0)
+ parser.buffer_size = parser.buffer_size // 2
+ self.assertEquals(parser.buffer_size, 1024)
+ parser.Parse(xml2, 1)
+ self.assertEquals(self.n, 4)
+
def test_main():
run_unittest(SetAttributeTest,
@@ -394,7 +519,8 @@ def test_main():
BufferTextTest,
HandlerExceptionTest,
PositionTest,
- sf1296433Test)
+ sf1296433Test,
+ ChardataBufferTest)
if __name__ == "__main__":
test_main()
diff --git a/Lib/test/test_socket.py b/Lib/test/test_socket.py
index bc31620..d474206 100644
--- a/Lib/test/test_socket.py
+++ b/Lib/test/test_socket.py
@@ -1133,7 +1133,7 @@ def isTipcAvailable():
for line in f:
if line.startswith("tipc "):
return True
- if test_support.debug:
+ if test_support.verbose:
print("TIPC module is not loaded, please 'sudo modprobe tipc'")
return False
diff --git a/Lib/test/test_winreg.py b/Lib/test/test_winreg.py
index 7b1baf8..3f73c74 100644
--- a/Lib/test/test_winreg.py
+++ b/Lib/test/test_winreg.py
@@ -73,26 +73,26 @@ class WinregTests(unittest.TestCase):
key = OpenKey(root_key, test_key_name)
# Read the sub-keys
- sub_key = OpenKey(key, subkeystr)
- # Check I can enumerate over the values.
- index = 0
- while 1:
- try:
- data = EnumValue(sub_key, index)
- except EnvironmentError:
- break
- self.assertEquals(data in test_data, True,
- "Didn't read back the correct test data")
- index = index + 1
- self.assertEquals(index, len(test_data),
- "Didn't read the correct number of items")
- # Check I can directly access each item
- for value_name, value_data, value_type in test_data:
- read_val, read_typ = QueryValueEx(sub_key, value_name)
- self.assertEquals(read_val, value_data,
- "Could not directly read the value")
- self.assertEquals(read_typ, value_type,
- "Could not directly read the value")
+ with OpenKey(key, "sub_key") as sub_key:
+ # Check I can enumerate over the values.
+ index = 0
+ while 1:
+ try:
+ data = EnumValue(sub_key, index)
+ except EnvironmentError:
+ break
+ self.assertEquals(data in test_data, True,
+ "Didn't read back the correct test data")
+ index = index + 1
+ self.assertEquals(index, len(test_data),
+ "Didn't read the correct number of items")
+ # Check I can directly access each item
+ for value_name, value_data, value_type in test_data:
+ read_val, read_typ = QueryValueEx(sub_key, value_name)
+ self.assertEquals(read_val, value_data,
+ "Could not directly read the value")
+ self.assertEquals(read_typ, value_type,
+ "Could not directly read the value")
sub_key.Close()
# Enumerate our main key.
read_val = EnumKey(key, 0)
@@ -155,6 +155,11 @@ class WinregTests(unittest.TestCase):
remote_key = ConnectRegistry(self.remote_name, HKEY_CURRENT_USER)
self.TestAll(remote_key)
+ def testExpandEnvironmentStrings(self):
+ r = ExpandEnvironmentStrings("%windir%\\test")
+ self.assertEqual(type(r), str)
+ self.assertEqual(r, os.environ["windir"] + "\\test")
+
def test_main():
test_support.run_unittest(WinregTests)