summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/howto/regex.rst2
-rw-r--r--Lib/httplib.py15
-rw-r--r--Lib/test/string_tests.py8
-rw-r--r--Lib/test/test_format.py20
-rw-r--r--Lib/test/test_httplib.py36
-rw-r--r--Misc/cheatsheet4
-rw-r--r--Modules/_ctypes/_ctypes_test.c2
-rw-r--r--Objects/unicodeobject.c44
8 files changed, 110 insertions, 21 deletions
diff --git a/Doc/howto/regex.rst b/Doc/howto/regex.rst
index 406ce1c..40f5fdb 100644
--- a/Doc/howto/regex.rst
+++ b/Doc/howto/regex.rst
@@ -203,7 +203,7 @@ this RE against the string ``abcbd``.
| | | ``bc``. |
+------+-----------+---------------------------------+
| 6 | ``abcb`` | Try ``b`` again. This time |
-| | | but the character at the |
+| | | the character at the |
| | | current position is ``'b'``, so |
| | | it succeeds. |
+------+-----------+---------------------------------+
diff --git a/Lib/httplib.py b/Lib/httplib.py
index 638a92b..de27c17 100644
--- a/Lib/httplib.py
+++ b/Lib/httplib.py
@@ -448,7 +448,12 @@ class HTTPResponse:
try:
self.length = int(length)
except ValueError:
- pass
+ self.length = None
+ else:
+ if self.length < 0: # ignore nonsensical negative lengths
+ self.length = None
+ else:
+ self.length = None
# does the body have a fixed length? (of zero)
if (status == NO_CONTENT or status == NOT_MODIFIED or
@@ -569,7 +574,13 @@ class HTTPResponse:
i = line.find(b";")
if i >= 0:
line = line[:i] # strip chunk-extensions
- chunk_left = int(line, 16)
+ try:
+ chunk_left = int(line, 16)
+ except ValueError:
+ # close the connection as protocol synchronisation is
+ # probably lost
+ self.close()
+ raise IncompleteRead(value)
if chunk_left == 0:
break
if amt is None:
diff --git a/Lib/test/string_tests.py b/Lib/test/string_tests.py
index 24fca59..caafb31 100644
--- a/Lib/test/string_tests.py
+++ b/Lib/test/string_tests.py
@@ -1053,7 +1053,13 @@ class MixinStrUnicodeUserStringTest:
# unicode raises ValueError, str raises OverflowError
self.checkraises((ValueError, OverflowError), '%c', '__mod__', ordinal)
+ longvalue = sys.maxsize + 10
+ slongvalue = str(longvalue)
+ if slongvalue[-1] in ("L","l"): slongvalue = slongvalue[:-1]
self.checkequal(' 42', '%3ld', '__mod__', 42)
+ self.checkequal('42', '%d', '__mod__', 42.0)
+ self.checkequal(slongvalue, '%d', '__mod__', longvalue)
+ self.checkcall('%d', '__mod__', float(longvalue))
self.checkequal('0042.00', '%07.2f', '__mod__', 42)
self.checkequal('0042.00', '%07.2F', '__mod__', 42)
@@ -1063,6 +1069,8 @@ class MixinStrUnicodeUserStringTest:
self.checkraises(TypeError, '%c', '__mod__', (None,))
self.checkraises(ValueError, '%(foo', '__mod__', {})
self.checkraises(TypeError, '%(foo)s %(bar)s', '__mod__', ('foo', 42))
+ self.checkraises(TypeError, '%d', '__mod__', "42") # not numeric
+ self.checkraises(TypeError, '%d', '__mod__', (42+0j)) # no int/long conversion provided
# argument names with properly nested brackets are supported
self.checkequal('bar', '%((foo))s', '__mod__', {'(foo)': 'bar'})
diff --git a/Lib/test/test_format.py b/Lib/test/test_format.py
index 9f4528c..7070286 100644
--- a/Lib/test/test_format.py
+++ b/Lib/test/test_format.py
@@ -11,7 +11,7 @@ maxsize = MAX_Py_ssize_t
overflowok = 1
overflowrequired = 0
-def testformat(formatstr, args, output=None):
+def testformat(formatstr, args, output=None, limit=None):
if verbose:
if output:
print("%r %% %r =? %r ..." %\
@@ -30,11 +30,22 @@ def testformat(formatstr, args, output=None):
if verbose:
print('no')
print("overflow expected on %r %% %r" % (formatstr, args))
- elif output and result != output:
+ elif output and limit is None and result != output:
if verbose:
print('no')
print("%r %% %r == %r != %r" %\
(formatstr, args, result, output))
+ # when 'limit' is specified, it determines how many characters
+ # must match exactly; lengths must always match.
+ # ex: limit=5, '12345678' matches '12345___'
+ # (mainly for floating point format tests for which an exact match
+ # can't be guaranteed due to rounding and representation errors)
+ elif output and limit is not None and (
+ len(result)!=len(output) or result[:limit]!=output[:limit]):
+ if verbose:
+ print('no')
+ print("%s %% %s == %s != %s" % \
+ (repr(formatstr), repr(args), repr(result), repr(output)))
else:
if verbose:
print('yes')
@@ -91,6 +102,7 @@ testformat("%.2d", big, "123456789012345678901234567890")
testformat("%.30d", big, "123456789012345678901234567890")
testformat("%.31d", big, "0123456789012345678901234567890")
testformat("%32.31d", big, " 0123456789012345678901234567890")
+testformat("%d", float(big), "123456________________________", 6)
big = 0x1234567890abcdef12345 # 21 hex digits
testformat("%x", big, "1234567890abcdef12345")
@@ -128,6 +140,7 @@ testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345")
testformat("%#+027.23X", big, "+0X0001234567890ABCDEF12345")
# same, except no 0 flag
testformat("%#+27.23X", big, " +0X001234567890ABCDEF12345")
+testformat("%x", float(big), "123456_______________", 6)
big = 0o12345670123456701234567012345670 # 32 octal digits
testformat("%o", big, "12345670123456701234567012345670")
@@ -169,6 +182,7 @@ testformat("%034.33o", big, "0012345670123456701234567012345670")
testformat("%0#38.33o", big, "0o000012345670123456701234567012345670")
# padding spaces come before marker
testformat("%#36.33o", big, " 0o012345670123456701234567012345670")
+testformat("%o", float(big), "123456__________________________", 6)
# Some small ints, in both Python int and long flavors).
testformat("%d", 42, "42")
@@ -186,11 +200,13 @@ testformat("%#X", 0, "0X0")
testformat("%x", 0x42, "42")
testformat("%x", -0x42, "-42")
+testformat("%x", float(0x42), "42")
testformat("%o", 0o42, "42")
testformat("%o", -0o42, "-42")
testformat("%o", 0o42, "42")
testformat("%o", -0o42, "-42")
+testformat("%o", float(0o42), "42")
# Test exception for unknown format characters
if verbose:
diff --git a/Lib/test/test_httplib.py b/Lib/test/test_httplib.py
index 4caf996..ca801da 100644
--- a/Lib/test/test_httplib.py
+++ b/Lib/test/test_httplib.py
@@ -159,6 +159,42 @@ class BasicTest(TestCase):
self.assertTrue(sock.data.startswith(expected), '%r != %r' %
(sock.data[:len(expected)], expected))
+ def test_chunked(self):
+ chunked_start = (
+ 'HTTP/1.1 200 OK\r\n'
+ 'Transfer-Encoding: chunked\r\n\r\n'
+ 'a\r\n'
+ 'hello worl\r\n'
+ '1\r\n'
+ 'd\r\n'
+ )
+ sock = FakeSocket(chunked_start + '0\r\n')
+ resp = httplib.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEquals(resp.read(), b'hello world')
+ resp.close()
+
+ for x in ('', 'foo\r\n'):
+ sock = FakeSocket(chunked_start + x)
+ resp = httplib.HTTPResponse(sock, method="GET")
+ resp.begin()
+ try:
+ resp.read()
+ except httplib.IncompleteRead as i:
+ self.assertEquals(i.partial, b'hello world')
+ else:
+ self.fail('IncompleteRead expected')
+ finally:
+ resp.close()
+
+ def test_negative_content_length(self):
+ sock = FakeSocket('HTTP/1.1 200 OK\r\nContent-Length: -1\r\n\r\nHello\r\n')
+ resp = httplib.HTTPResponse(sock, method="GET")
+ resp.begin()
+ self.assertEquals(resp.read(), b'Hello\r\n')
+ resp.close()
+
+
class OfflineTest(TestCase):
def test_responses(self):
self.assertEquals(httplib.responses[httplib.NOT_FOUND], "Not Found")
diff --git a/Misc/cheatsheet b/Misc/cheatsheet
index c530442..cc56036 100644
--- a/Misc/cheatsheet
+++ b/Misc/cheatsheet
@@ -561,8 +561,8 @@ d Signed integer decimal.
i Signed integer decimal.
o Unsigned octal.
u Unsigned decimal.
-x Unsigned hexidecimal (lowercase).
-X Unsigned hexidecimal (uppercase).
+x Unsigned hexadecimal (lowercase).
+X Unsigned hexadecimal (uppercase).
e Floating point exponential format (lowercase).
E Floating point exponential format (uppercase).
f Floating point decimal format.
diff --git a/Modules/_ctypes/_ctypes_test.c b/Modules/_ctypes/_ctypes_test.c
index 7048a2e..63fb580 100644
--- a/Modules/_ctypes/_ctypes_test.c
+++ b/Modules/_ctypes/_ctypes_test.c
@@ -398,7 +398,7 @@ EXPORT(int) unpack_bitfields(struct BITS *bits, char name)
return 0;
}
-PyMethodDef module_methods[] = {
+static PyMethodDef module_methods[] = {
/* {"get_last_tf_arg_s", get_last_tf_arg_s, METH_NOARGS},
{"get_last_tf_arg_u", get_last_tf_arg_u, METH_NOARGS},
*/
diff --git a/Objects/unicodeobject.c b/Objects/unicodeobject.c
index 86d8b54..7359821 100644
--- a/Objects/unicodeobject.c
+++ b/Objects/unicodeobject.c
@@ -8600,6 +8600,7 @@ PyObject *PyUnicode_Format(PyObject *format,
int prec = -1;
Py_UNICODE c = '\0';
Py_UNICODE fill;
+ int isnumok;
PyObject *v = NULL;
PyObject *temp = NULL;
Py_UNICODE *pbuf;
@@ -8804,21 +8805,38 @@ PyObject *PyUnicode_Format(PyObject *format,
case 'X':
if (c == 'i')
c = 'd';
- if (PyLong_Check(v)) {
- temp = formatlong(v, flags, prec, c);
- if (!temp)
- goto onError;
- pbuf = PyUnicode_AS_UNICODE(temp);
- len = PyUnicode_GET_SIZE(temp);
- sign = 1;
+ isnumok = 0;
+ if (PyNumber_Check(v)) {
+ PyObject *iobj=NULL;
+
+ if (PyLong_Check(v)) {
+ iobj = v;
+ Py_INCREF(iobj);
+ }
+ else {
+ iobj = PyNumber_Long(v);
+ }
+ if (iobj!=NULL) {
+ if (PyLong_Check(iobj)) {
+ isnumok = 1;
+ temp = formatlong(iobj, flags, prec, c);
+ Py_DECREF(iobj);
+ if (!temp)
+ goto onError;
+ pbuf = PyUnicode_AS_UNICODE(temp);
+ len = PyUnicode_GET_SIZE(temp);
+ sign = 1;
+ }
+ else {
+ Py_DECREF(iobj);
+ }
+ }
}
- else {
- pbuf = formatbuf;
- len = formatint(pbuf, sizeof(formatbuf)/sizeof(Py_UNICODE),
- flags, prec, c, v);
- if (len < 0)
+ if (!isnumok) {
+ PyErr_Format(PyExc_TypeError,
+ "%%%c format: a number is required, "
+ "not %.200s", c, Py_TYPE(v)->tp_name);
goto onError;
- sign = 1;
}
if (flags & F_ZERO)
fill = '0';