Skip to content

Commit 9ab96d4

Browse files
committed
Changes by Eric Raymond:
1. Generate a correct Content-Length header visible through the info() method if a request to open an FTP URL gets a length in the response to RETR. 2. Take a third argument to urlretrieve() that makes it possible to progress- meter an urlretrieve call (this is what I needed the above change for). See the second patch band below for details. 3. To avoid spurious errors, I commented out the gopher test. The target document no longer exists.
1 parent d5af7bd commit 9ab96d4

File tree

1 file changed

+32
-14
lines changed

1 file changed

+32
-14
lines changed

Lib/urllib.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,14 +59,11 @@ def urlopen(url, data=None):
5959
return _urlopener.open(url)
6060
else:
6161
return _urlopener.open(url, data)
62-
def urlretrieve(url, filename=None):
62+
def urlretrieve(url, filename=None, reporthook=None):
6363
global _urlopener
6464
if not _urlopener:
6565
_urlopener = FancyURLopener()
66-
if filename:
67-
return _urlopener.retrieve(url, filename)
68-
else:
69-
return _urlopener.retrieve(url)
66+
return _urlopener.retrieve(url, filename, reporthook)
7067
def urlcleanup():
7168
if _urlopener:
7269
_urlopener.cleanup()
@@ -171,7 +168,7 @@ def open_unknown(self, fullurl, data=None):
171168
# External interface
172169
# retrieve(url) returns (filename, None) for a local object
173170
# or (tempfilename, headers) for a remote object
174-
def retrieve(self, url, filename=None):
171+
def retrieve(self, url, filename=None, reporthook=None):
175172
url = unwrap(url)
176173
if self.tempcache and self.tempcache.has_key(url):
177174
return self.tempcache[url]
@@ -200,10 +197,21 @@ def retrieve(self, url, filename=None):
200197
self.tempcache[url] = result
201198
tfp = open(filename, 'wb')
202199
bs = 1024*8
200+
size = -1
201+
blocknum = 1
202+
if reporthook:
203+
if headers.has_key("content-length"):
204+
size = int(headers["Content-Length"])
205+
reporthook(0, bs, size)
203206
block = fp.read(bs)
207+
if reporthook:
208+
reporthook(1, bs, size)
204209
while block:
205210
tfp.write(block)
206211
block = fp.read(bs)
212+
blocknum = blocknum + 1
213+
if reporthook:
214+
reporthook(blocknum, bs, size)
207215
fp.close()
208216
tfp.close()
209217
del fp
@@ -366,9 +374,14 @@ def open_ftp(self, url):
366374
if string.lower(attr) == 'type' and \
367375
value in ('a', 'A', 'i', 'I', 'd', 'D'):
368376
type = string.upper(value)
369-
return addinfourl(
370-
self.ftpcache[key].retrfile(file, type),
371-
noheaders(), "ftp:" + url)
377+
(fp, retrlen) = self.ftpcache[key].retrfile(file, type)
378+
if retrlen >= 0:
379+
import mimetools, StringIO
380+
headers = mimetools.Message(StringIO.StringIO(
381+
'Content-Length: %d\n' % retrlen))
382+
else:
383+
headers = noheaders()
384+
return addinfourl(fp, headers, "ftp:" + url)
372385
except ftperrors(), msg:
373386
raise IOError, ('ftp error', msg), sys.exc_info()[2]
374387

@@ -574,7 +587,7 @@ def retrfile(self, file, type):
574587
# Try to retrieve as a file
575588
try:
576589
cmd = 'RETR ' + file
577-
conn = self.ftp.transfercmd(cmd)
590+
conn = self.ftp.ntransfercmd(cmd)
578591
except ftplib.error_perm, reason:
579592
if reason[:3] != '550':
580593
raise IOError, ('ftp error', reason), \
@@ -585,9 +598,10 @@ def retrfile(self, file, type):
585598
# Try a directory listing
586599
if file: cmd = 'LIST ' + file
587600
else: cmd = 'LIST'
588-
conn = self.ftp.transfercmd(cmd)
601+
conn = self.ftp.ntransfercmd(cmd)
589602
self.busy = 1
590-
return addclosehook(conn.makefile('rb'), self.endtransfer)
603+
# Pass back both a suitably decorated object and a retrieval length
604+
return (addclosehook(conn[0].makefile('rb'), self.endtransfer), conn[1])
591605
def endtransfer(self):
592606
if not self.busy:
593607
return
@@ -977,6 +991,10 @@ def test1():
977991
print round(t1 - t0, 3), 'sec'
978992

979993

994+
def reporthook(blocknum, blocksize, totalsize):
995+
# Report during remote transfers
996+
print "Block number: %d, Block size: %d, Total size: %d" % (blocknum, blocksize, totalsize)
997+
980998
# Test program
981999
def test(args=[]):
9821000
if not args:
@@ -985,13 +1003,13 @@ def test(args=[]):
9851003
'file:/etc/passwd',
9861004
'file://localhost/etc/passwd',
9871005
'ftp://ftp.python.org/etc/passwd',
988-
'gopher://gopher.micro.umn.edu/1/',
1006+
## 'gopher://gopher.micro.umn.edu/1/',
9891007
'http://www.python.org/index.html',
9901008
]
9911009
try:
9921010
for url in args:
9931011
print '-'*10, url, '-'*10
994-
fn, h = urlretrieve(url)
1012+
fn, h = urlretrieve(url, None, reporthook)
9951013
print fn, h
9961014
if h:
9971015
print '======'

0 commit comments

Comments
 (0)