[Python-checkins] r69514 - in python/branches/release30-maint: Lib/http/client.py Lib/io.py Lib/test/test_httplib.py Lib/test/test_io.py Lib/test/test_urllib2_localnet.py Lib/test/test_urllib2net.py Lib/urllib/request.py Lib/urllib/response.py Misc/NEWS

antoine.pitrou python-checkins at python.org
Wed Feb 11 02:01:42 CET 2009


Author: antoine.pitrou
Date: Wed Feb 11 02:01:41 2009
New Revision: 69514

Log:
Merged revisions 69513 via svnmerge from 
svn+ssh://pythondev@svn.python.org/python/branches/py3k

........
  r69513 | antoine.pitrou | 2009-02-11 01:39:14 +0100 (mer., 11 févr. 2009) | 3 lines
  
  Issue #4631: Fix urlopen() result when an HTTP response uses chunked encoding.
........


Modified:
   python/branches/release30-maint/   (props changed)
   python/branches/release30-maint/Lib/http/client.py
   python/branches/release30-maint/Lib/io.py
   python/branches/release30-maint/Lib/test/test_httplib.py
   python/branches/release30-maint/Lib/test/test_io.py
   python/branches/release30-maint/Lib/test/test_urllib2_localnet.py
   python/branches/release30-maint/Lib/test/test_urllib2net.py
   python/branches/release30-maint/Lib/urllib/request.py
   python/branches/release30-maint/Lib/urllib/response.py
   python/branches/release30-maint/Misc/NEWS

Modified: python/branches/release30-maint/Lib/http/client.py
==============================================================================
--- python/branches/release30-maint/Lib/http/client.py	(original)
+++ python/branches/release30-maint/Lib/http/client.py	Wed Feb 11 02:01:41 2009
@@ -249,7 +249,7 @@
 
     return email.parser.Parser(_class=HTTPMessage).parsestr(hstring)
 
-class HTTPResponse:
+class HTTPResponse(io.RawIOBase):
 
     # strict: If true, raise BadStatusLine if the status line can't be
     # parsed as a valid HTTP/1.0 or 1.1 status line.  By default it is
@@ -471,8 +471,6 @@
         #          called, meaning self.isclosed() is meaningful.
         return self.fp is None
 
-    # XXX It would be nice to have readline and __iter__ for this, too.
-
     def read(self, amt=None):
         if self.fp is None:
             return b""
@@ -585,6 +583,9 @@
             amt -= len(chunk)
         return b"".join(s)
 
+    def fileno(self):
+        return self.fp.fileno()
+
     def getheader(self, name, default=None):
         if self.msg is None:
             raise ResponseNotReady()
@@ -596,6 +597,11 @@
             raise ResponseNotReady()
         return list(self.msg.items())
 
+    # We override IOBase.__iter__ so that it doesn't check for closed-ness
+
+    def __iter__(self):
+        return self
+
 
 class HTTPConnection:
 

Modified: python/branches/release30-maint/Lib/io.py
==============================================================================
--- python/branches/release30-maint/Lib/io.py	(original)
+++ python/branches/release30-maint/Lib/io.py	Wed Feb 11 02:01:41 2009
@@ -491,7 +491,6 @@
         terminator(s) recognized.
         """
         # For backwards compatibility, a (slowish) readline().
-        self._checkClosed()
         if hasattr(self, "peek"):
             def nreadahead():
                 readahead = self.peek(1)
@@ -533,7 +532,6 @@
         lines will be read if the total size (in bytes/characters) of all
         lines so far exceeds hint.
         """
-        self._checkClosed()
         if hint is None or hint <= 0:
             return list(self)
         n = 0

Modified: python/branches/release30-maint/Lib/test/test_httplib.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_httplib.py	(original)
+++ python/branches/release30-maint/Lib/test/test_httplib.py	Wed Feb 11 02:01:41 2009
@@ -42,7 +42,6 @@
             raise AssertionError('caller tried to read past EOF')
         return data
 
-
 class HeaderTests(TestCase):
     def test_auto_headers(self):
         # Some headers are added automatically, but should not be added by
@@ -245,7 +244,6 @@
         self.assertEqual(httpConn.sock.gettimeout(), 30)
         httpConn.close()
 
-
 class HTTPSTimeoutTest(TestCase):
 # XXX Here should be tests for HTTPS, there isn't any right now!
 
@@ -257,7 +255,7 @@
 
 def test_main(verbose=None):
     support.run_unittest(HeaderTests, OfflineTest, BasicTest, TimeoutTest,
-                              HTTPSTimeoutTest)
+                         HTTPSTimeoutTest)
 
 if __name__ == '__main__':
     test_main()

Modified: python/branches/release30-maint/Lib/test/test_io.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_io.py	(original)
+++ python/branches/release30-maint/Lib/test/test_io.py	Wed Feb 11 02:01:41 2009
@@ -1359,6 +1359,7 @@
             self.assertRaises(ValueError, f.fileno)
             self.assertRaises(ValueError, f.isatty)
             self.assertRaises(ValueError, f.__iter__)
+            self.assertRaises(ValueError, next, f)
             if hasattr(f, "peek"):
                 self.assertRaises(ValueError, f.peek, 1)
             self.assertRaises(ValueError, f.read)

Modified: python/branches/release30-maint/Lib/test/test_urllib2_localnet.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_urllib2_localnet.py	(original)
+++ python/branches/release30-maint/Lib/test/test_urllib2_localnet.py	Wed Feb 11 02:01:41 2009
@@ -310,7 +310,7 @@
             self.send_response(response_code)
 
             for (header, value) in headers:
-                self.send_header(header, value % self.port)
+                self.send_header(header, value % {'port':self.port})
             if body:
                 self.send_header("Content-type", "text/plain")
                 self.end_headers()
@@ -341,10 +341,17 @@
             self.server.stop()
 
     def urlopen(self, url, data=None):
+        l = []
         f = urllib.request.urlopen(url, data)
-        result = f.read()
-        f.close()
-        return result
+        try:
+            # Exercise various methods
+            l.extend(f.readlines(200))
+            l.append(f.readline())
+            l.append(f.read(1024))
+            l.append(f.read())
+        finally:
+            f.close()
+        return b"".join(l)
 
     def start_server(self, responses=None):
         if responses is None:
@@ -361,7 +368,8 @@
     def test_redirection(self):
         expected_response = b"We got here..."
         responses = [
-            (302, [("Location", "http://localhost:%s/somewhere_else")], ""),
+            (302, [("Location", "http://localhost:%(port)s/somewhere_else")],
+             ""),
             (200, [], expected_response)
         ]
 
@@ -370,6 +378,20 @@
         self.assertEquals(data, expected_response)
         self.assertEquals(handler.requests, ["/", "/somewhere_else"])
 
+    def test_chunked(self):
+        expected_response = b"hello world"
+        chunked_start = (
+                        b'a\r\n'
+                        b'hello worl\r\n'
+                        b'1\r\n'
+                        b'd\r\n'
+                        b'0\r\n'
+                        )
+        response = [(200, [("Transfer-Encoding", "chunked")], chunked_start)]
+        handler = self.start_server(response)
+        data = self.urlopen("http://localhost:%s/" % handler.port)
+        self.assertEquals(data, expected_response)
+
     def test_404(self):
         expected_response = b"Bad bad bad..."
         handler = self.start_server([(404, [], expected_response)])

Modified: python/branches/release30-maint/Lib/test/test_urllib2net.py
==============================================================================
--- python/branches/release30-maint/Lib/test/test_urllib2net.py	(original)
+++ python/branches/release30-maint/Lib/test/test_urllib2net.py	Wed Feb 11 02:01:41 2009
@@ -195,7 +195,8 @@
     def test_http_basic(self):
         self.assertTrue(socket.getdefaulttimeout() is None)
         u = _urlopen_with_retry("http://www.python.org")
-        self.assertTrue(u.fp._sock.gettimeout() is None)
+        #self.assertTrue(u.fp._sock.gettimeout() is None)
+        self.assertTrue(u.fp.fp._sock.gettimeout() is None)
 
     def test_http_default_timeout(self):
         self.assertTrue(socket.getdefaulttimeout() is None)
@@ -204,7 +205,8 @@
             u = _urlopen_with_retry("http://www.python.org")
         finally:
             socket.setdefaulttimeout(None)
-        self.assertEqual(u.fp._sock.gettimeout(), 60)
+        #self.assertEqual(u.fp._sock.gettimeout(), 60)
+        self.assertEqual(u.fp.fp._sock.gettimeout(), 60)
 
     def test_http_no_timeout(self):
         self.assertTrue(socket.getdefaulttimeout() is None)
@@ -213,11 +215,13 @@
             u = _urlopen_with_retry("http://www.python.org", timeout=None)
         finally:
             socket.setdefaulttimeout(None)
-        self.assertTrue(u.fp._sock.gettimeout() is None)
+        #self.assertTrue(u.fp._sock.gettimeout() is None)
+        self.assertTrue(u.fp.fp._sock.gettimeout() is None)
 
     def test_http_timeout(self):
         u = _urlopen_with_retry("http://www.python.org", timeout=120)
-        self.assertEqual(u.fp._sock.gettimeout(), 120)
+        #self.assertEqual(u.fp._sock.gettimeout(), 120)
+        self.assertEqual(u.fp.fp._sock.gettimeout(), 120)
 
     FTP_HOST = "ftp://ftp.mirror.nl/pub/mirror/gnu/"
 

Modified: python/branches/release30-maint/Lib/urllib/request.py
==============================================================================
--- python/branches/release30-maint/Lib/urllib/request.py	(original)
+++ python/branches/release30-maint/Lib/urllib/request.py	Wed Feb 11 02:01:41 2009
@@ -333,7 +333,6 @@
         handlers = chain.get(kind, ())
         for handler in handlers:
             func = getattr(handler, meth_name)
-
             result = func(*args)
             if result is not None:
                 return result
@@ -1070,7 +1069,8 @@
         except socket.error as err: # XXX what error?
             raise URLError(err)
 
-        resp = addinfourl(r.fp, r.msg, req.get_full_url())
+##        resp = addinfourl(r.fp, r.msg, req.get_full_url())
+        resp = addinfourl(r, r.msg, req.get_full_url())
         resp.code = r.status
         resp.msg = r.reason
         return resp
@@ -1606,7 +1606,7 @@
         # According to RFC 2616, "2xx" code indicates that the client's
         # request was successfully received, understood, and accepted.
         if 200 <= response.status < 300:
-            return addinfourl(response.fp, response.msg, "http:" + url,
+            return addinfourl(response, response.msg, "http:" + url,
                               response.status)
         else:
             return self.http_error(

Modified: python/branches/release30-maint/Lib/urllib/response.py
==============================================================================
--- python/branches/release30-maint/Lib/urllib/response.py	(original)
+++ python/branches/release30-maint/Lib/urllib/response.py	Wed Feb 11 02:01:41 2009
@@ -17,7 +17,8 @@
         self.read = self.fp.read
         self.readline = self.fp.readline
         # TODO(jhylton): Make sure an object with readlines() is also iterable
-        if hasattr(self.fp, "readlines"): self.readlines = self.fp.readlines
+        if hasattr(self.fp, "readlines"):
+            self.readlines = self.fp.readlines
         if hasattr(self.fp, "fileno"):
             self.fileno = self.fp.fileno
         else:

Modified: python/branches/release30-maint/Misc/NEWS
==============================================================================
--- python/branches/release30-maint/Misc/NEWS	(original)
+++ python/branches/release30-maint/Misc/NEWS	Wed Feb 11 02:01:41 2009
@@ -116,6 +116,9 @@
 Library
 -------
 
+- Issue #4631: Fix urlopen() result when an HTTP response uses chunked
+  encoding.
+
 - Issue #5203: Fixed ctypes segfaults when passing a unicode string to a
   function without argtypes (only occurs if HAVE_USABLE_WCHAR_T is false).
 


More information about the Python-checkins mailing list