ayrıca buildfarm'da arada bir aldığımız race conditional hatanın (NonType object has no attribute: split) sebebini de buldum ve fix ettim.. urllib'i alnından öpüyoruz..
This commit is contained in:
A. Murat Eren
2006-03-25 13:46:43 +00:00
parent 1d076d3db2
commit a58abe89c7
+42 -25
View File
@@ -42,10 +42,14 @@ from pisi.uri import URI
class FetchError(pisi.Error): class FetchError(pisi.Error):
pass pass
class RangeError(pisi.Error):
pass
# helper functions # helper functions
def fetch_url(url, dest, progress=None): def fetch_url(url, destdir, progress=None, resume=True):
fetch = Fetcher(url, dest) fetch = Fetcher(url, destdir)
if not resume:
fetch.resume = False
fetch.progress = progress fetch.progress = progress
fetch.fetch() fetch.fetch()
if progress: if progress:
@@ -55,14 +59,15 @@ def fetch_url(url, dest, progress=None):
class Fetcher: class Fetcher:
"""Fetcher can fetch a file from various sources using various """Fetcher can fetch a file from various sources using various
protocols.""" protocols."""
def __init__(self, url, dest): def __init__(self, url, destdir, resume = True):
if not isinstance(url, URI): if not isinstance(url, URI):
url = URI(url) url = URI(url)
self.resume = resume
self.scheme = url.scheme() self.scheme = url.scheme()
self.url = url self.url = url
self.filedest = dest self.destdir = destdir
util.check_dir(self.filedest) util.check_dir(self.destdir)
self.eta = '??:??:??' self.eta = '??:??:??'
self.percent = 0 self.percent = 0
self.rate = 0.0 self.rate = 0.0
@@ -75,24 +80,26 @@ class Fetcher:
if not self.url.filename(): if not self.url.filename():
self.err(_('Filename error')) self.err(_('Filename error'))
if not os.access(self.filedest, os.W_OK): if not os.access(self.destdir, os.W_OK):
self.err(_('Access denied to write to destination directory')) self.err(_('Access denied to write to destination directory: "%s"' % (self.destdir)))
archive_file = os.path.join(self.filedest, self.url.filename()) archive_file = os.path.join(self.destdir, self.url.filename())
if os.path.exists(self.filedest) and not os.access(self.filedest, os.W_OK): if os.path.exists(archive_file) and not os.access(archive_file, os.W_OK):
self.err(_('Access denied to destination file')) self.err(_('Access denied to destination file: "%s"' % (archive_file)))
partial_file = archive_file + '.part'
if self.url.is_local_file(): if self.url.is_local_file():
self.fetchLocalFile(archive_file + '.part') self.fetchLocalFile(partial_file)
else: else:
self.fetchRemoteFile(archive_file + '.part') self.fetchRemoteFile(partial_file)
if os.stat(archive_file + '.part').st_size == 0: if os.stat(partial_file).st_size == 0:
os.remove(archive_file + '.part') os.remove(partial_file)
self.err(_('A problem occured. Please check the archive address and/or permissions again.')) self.err(_('A problem occured. Please check the archive address and/or permissions again.'))
else:
move(archive_file + '.part', archive_file) move(partial_file, archive_file)
return archive_file return archive_file
@@ -158,19 +165,25 @@ class Fetcher:
def fetchRemoteFile (self, archive_file): def fetchRemoteFile (self, archive_file):
from httplib import HTTPException from httplib import HTTPException
if os.path.exists(archive_file): if os.path.exists(archive_file) and self.resume:
if self.scheme == 'http' or self.scheme == 'https' or self.scheme == 'ftp': if self.scheme == 'http' or self.scheme == 'https' or self.scheme == 'ftp':
self.exist_size = os.path.getsize(archive_file) self.exist_size = os.path.getsize(archive_file)
dest = open(archive_file, 'ab') dest = open(archive_file, 'ab')
else: else:
dest = open(archive_file, 'wb') dest = open(archive_file, 'wb')
uri = self.url.get_uri() uri = self.url.get_uri()
flag = 1 flag = 1
try: try:
try: try:
fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri))) try:
fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri)))
except RangeError:
ctx.ui.info(_('Requested range not satisfiable, starting again.'))
dest = open(archive_file, 'wb')
self.exist_size = 0
fileObj = urllib2.urlopen(self.formatRequest(urllib2.Request(uri)))
headers = fileObj.info() headers = fileObj.info()
flag = 0 flag = 0
except ValueError, e: except ValueError, e:
@@ -247,7 +260,7 @@ class HTTPRangeHandler(urllib2.BaseHandler):
def http_error_416(self, request, fp, errcode, msg, headers): def http_error_416(self, request, fp, errcode, msg, headers):
# HTTP 1.1's 'Range Not Satisfiable' error.. # HTTP 1.1's 'Range Not Satisfiable' error..
raise FetchError(_('Requested range not satisfiable')) raise RangeError
class FTPRangeHandler(urllib2.FTPHandler): class FTPRangeHandler(urllib2.FTPHandler):
@@ -264,6 +277,7 @@ class FTPRangeHandler(urllib2.FTPHandler):
host = socket.gethostbyname(host) host = socket.gethostbyname(host)
except socket.error, msg: except socket.error, msg:
raise FetchError(msg) raise FetchError(msg)
path, attrs = urllib.splitattr(req.get_selector()) path, attrs = urllib.splitattr(req.get_selector())
dirs = path.split('/') dirs = path.split('/')
dirs = map(urllib.unquote, dirs) dirs = map(urllib.unquote, dirs)
@@ -278,19 +292,22 @@ class FTPRangeHandler(urllib2.FTPHandler):
if attr.lower() == 'type' and \ if attr.lower() == 'type' and \
value in ('a', 'A', 'i', 'I', 'd', 'D'): value in ('a', 'A', 'i', 'I', 'd', 'D'):
type = value.upper() type = value.upper()
rawr = req.headers.get('Range', None) rawr = req.headers.get('Range', None)
rest = int(rawr.split("=")[1].rstrip("-")) if rawr:
rest = int(rawr.split("=")[1].rstrip("-"))
else:
rest = 0
fp, retrlen = fw.retrfile(file, type, rest) fp, retrlen = fw.retrfile(file, type, rest)
fb, lb = rest, retrlen fb, lb = rest, retrlen
if retrlen is None or retrlen == 0: if retrlen is None or retrlen == 0:
raise FetchError(_('Requested Range Not Satisfiable')) raise RangeError
retrlen = lb - fb retrlen = lb - fb
if retrlen < 0: if retrlen < 0:
# beginning of range is larger than file # beginning of range is larger than file
raise FetchError(_('Requested Range Not Satisfiable')) raise RangeError
headers = '' headers = ''
mtype = guess_type(req.get_full_url())[0] mtype = guess_type(req.get_full_url())[0]