Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit ab06e3f

Browse files
committed
merge from 3.2 - Fix issue 10817 - Fix urlretrieve function to raise ContentTooShortError
even when reporthook is None. Patch by Jyrki Pulliainen.
2 parents 6a57afe + ce26014 commit ab06e3f

3 files changed

Lines changed: 87 additions & 29 deletions

File tree

Lib/test/test_urllib.py

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,44 @@ def urlopen(url, data=None, proxies=None):
3636
else:
3737
return opener.open(url, data)
3838

39+
40+
class FakeHTTPMixin(object):
41+
def fakehttp(self, fakedata):
42+
class FakeSocket(io.BytesIO):
43+
io_refs = 1
44+
45+
def sendall(self, str):
46+
pass
47+
48+
def makefile(self, *args, **kwds):
49+
self.io_refs += 1
50+
return self
51+
52+
def read(self, amt=None):
53+
if self.closed:
54+
return b""
55+
return io.BytesIO.read(self, amt)
56+
57+
def readline(self, length=None):
58+
if self.closed:
59+
return b""
60+
return io.BytesIO.readline(self, length)
61+
62+
def close(self):
63+
self.io_refs -= 1
64+
if self.io_refs == 0:
65+
io.BytesIO.close(self)
66+
67+
class FakeHTTPConnection(http.client.HTTPConnection):
68+
def connect(self):
69+
self.sock = FakeSocket(fakedata)
70+
self._connection_class = http.client.HTTPConnection
71+
http.client.HTTPConnection = FakeHTTPConnection
72+
73+
def unfakehttp(self):
74+
http.client.HTTPConnection = self._connection_class
75+
76+
3977
class urlopen_FileTests(unittest.TestCase):
4078
"""Test urlopen() opening a temporary file.
4179
@@ -139,35 +177,9 @@ def test_getproxies_environment_keep_no_proxies(self):
139177
self.env.set('NO_PROXY', 'localhost, anotherdomain.com, newdomain.com')
140178
self.assertTrue(urllib.request.proxy_bypass_environment('anotherdomain.com'))
141179

142-
class urlopen_HttpTests(unittest.TestCase):
180+
class urlopen_HttpTests(unittest.TestCase, FakeHTTPMixin):
143181
"""Test urlopen() opening a fake http connection."""
144182

145-
def fakehttp(self, fakedata):
146-
class FakeSocket(io.BytesIO):
147-
io_refs = 1
148-
def sendall(self, str): pass
149-
def makefile(self, *args, **kwds):
150-
self.io_refs += 1
151-
return self
152-
def read(self, amt=None):
153-
if self.closed: return b""
154-
return io.BytesIO.read(self, amt)
155-
def readline(self, length=None):
156-
if self.closed: return b""
157-
return io.BytesIO.readline(self, length)
158-
def close(self):
159-
self.io_refs -= 1
160-
if self.io_refs == 0:
161-
io.BytesIO.close(self)
162-
class FakeHTTPConnection(http.client.HTTPConnection):
163-
def connect(self):
164-
self.sock = FakeSocket(fakedata)
165-
self._connection_class = http.client.HTTPConnection
166-
http.client.HTTPConnection = FakeHTTPConnection
167-
168-
def unfakehttp(self):
169-
http.client.HTTPConnection = self._connection_class
170-
171183
def check_read(self, ver):
172184
self.fakehttp(b"HTTP/" + ver + b" 200 OK\r\n\r\nHello!")
173185
try:
@@ -394,6 +406,48 @@ def hooktester(count, block_size, total_size, _report=report):
394406
self.assertEqual(report[0][1], 8192)
395407
self.assertEqual(report[0][2], 8193)
396408

409+
410+
class urlretrieve_HttpTests(unittest.TestCase, FakeHTTPMixin):
411+
"""Test urllib.urlretrieve() using fake http connections"""
412+
413+
def test_short_content_raises_ContentTooShortError(self):
414+
self.fakehttp(b'''HTTP/1.1 200 OK
415+
Date: Wed, 02 Jan 2008 03:03:54 GMT
416+
Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
417+
Connection: close
418+
Content-Length: 100
419+
Content-Type: text/html; charset=iso-8859-1
420+
421+
FF
422+
''')
423+
424+
def _reporthook(par1, par2, par3):
425+
pass
426+
427+
with self.assertRaises(urllib.error.ContentTooShortError):
428+
try:
429+
urllib.request.urlretrieve('http://example.com/',
430+
reporthook=_reporthook)
431+
finally:
432+
self.unfakehttp()
433+
434+
def test_short_content_raises_ContentTooShortError_without_reporthook(self):
435+
self.fakehttp(b'''HTTP/1.1 200 OK
436+
Date: Wed, 02 Jan 2008 03:03:54 GMT
437+
Server: Apache/1.3.33 (Debian GNU/Linux) mod_ssl/2.8.22 OpenSSL/0.9.7e
438+
Connection: close
439+
Content-Length: 100
440+
Content-Type: text/html; charset=iso-8859-1
441+
442+
FF
443+
''')
444+
with self.assertRaises(urllib.error.ContentTooShortError):
445+
try:
446+
urllib.request.urlretrieve('http://example.com/')
447+
finally:
448+
self.unfakehttp()
449+
450+
397451
class QuotingTests(unittest.TestCase):
398452
"""Tests for urllib.quote() and urllib.quote_plus()
399453
@@ -1186,6 +1240,7 @@ def test_main():
11861240
urlopen_FileTests,
11871241
urlopen_HttpTests,
11881242
urlretrieve_FileTests,
1243+
urlretrieve_HttpTests,
11891244
ProxyTests,
11901245
QuotingTests,
11911246
UnquotingTests,

Lib/urllib/request.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1605,9 +1605,9 @@ def retrieve(self, url, filename=None, reporthook=None, data=None):
16051605
size = -1
16061606
read = 0
16071607
blocknum = 0
1608+
if "content-length" in headers:
1609+
size = int(headers["Content-Length"])
16081610
if reporthook:
1609-
if "content-length" in headers:
1610-
size = int(headers["Content-Length"])
16111611
reporthook(blocknum, bs, size)
16121612
while 1:
16131613
block = fp.read(bs)

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,9 @@ Core and Builtins
347347
Library
348348
-------
349349

350+
- Issue 10817: Fix urlretrieve function to raise ContentTooShortError even
351+
when reporthook is None. Patch by Jyrki Pulliainen.
352+
350353
- Issue 13296: Fix IDLE to clear compile __future__ flags on shell restart.
351354
(Patch by Roger Serwy)
352355

0 commit comments

Comments
 (0)