'This is a convenience method for downloading a file from an URL.
Normally, this will be a file from the index, though currently
no check is made for this (i.e. a file can be downloaded from
anywhere).
The method is just like the :func:`urlretrieve` function in the
standard library, except that it allows digest computation to be
done during download and checking that the downloaded data
matched any expected value.
:param url: The URL of the file to be downloaded (assumed to be
available via an HTTP GET request).
:param destfile: The pathname where the downloaded file is to be
saved.
:param digest: If specified, this must be a (hasher, value)
tuple, where hasher is the algorithm used (e.g.
``\'md5\'``) and ``value`` is the expected value.
:param reporthook: The same as for :func:`urlretrieve` in the
standard library.'

def download_file(self, url, destfile, digest=None, reporthook=None):

    if (digest is None):
        digester = None
        logger.debug('No    digest    specified')
    else:
        if isinstance(digest, (list, tuple)):
            (hasher, digest) = digest
        else:
            hasher = 'md5'
        digester = getattr(hashlib, hasher)()
        logger.debug(('Digest    specified:    %s' % digest))
    with open(destfile, 'wb') as dfp:
        sfp = self.send_request(Request(url))
        try:
            headers = sfp.info()
            blocksize = 8192
            size = (-1)
            read = 0
            blocknum = 0
            if ('content-length' in headers):
                size = int(headers['Content-Length'])
            if reporthook:
                reporthook(blocknum, blocksize, size)
            while True:
                block = sfp.read(blocksize)
                if (not block):
                    break
                read += len(block)
                dfp.write(block)
                if digester:
                    digester.update(block)
                blocknum += 1
                if reporthook:
                    reporthook(blocknum, blocksize, size)
        finally:
            sfp.close()
    if ((size >= 0) and (read < size)):
        raise DistlibException(('retrieval    incomplete:    got    only    %d    out    of    %d    bytes' % (read, size)))
    if digester:
        actual = digester.hexdigest()
        if (digest != actual):
            raise DistlibException(('%s    digest    mismatch    for    %s:    expected    %s,    got    %s' % (hasher, destfile, digest, actual)))
        logger.debug('Digest    verified:    %s', digest)
