def download_file(self, url, destfile, digest=None, reporthook=None):
if digest is None:<EOL><INDENT>digester = None<EOL>logger.debug('<STR_LIT>')<EOL><DEDENT>else:<EOL><INDENT>if isinstance(digest, (list, tuple)):<EOL><INDENT>hasher, digest = digest<EOL><DEDENT>else:<EOL><INDENT>hasher = '<STR_LIT>'<EOL><DEDENT>digester = getattr(hashlib, hasher)()<EOL>logger.debug('<STR_LIT>' % digest)<EOL><DEDENT>with open(destfile, '<STR_LIT:wb>') as dfp:<EOL><INDENT>sfp = self.send_request(Request(url))<EOL>try:<EOL><INDENT>headers = sfp.info()<EOL>blocksize = <NUM_LIT><EOL>size = -<NUM_LIT:1><EOL>read = <NUM_LIT:0><EOL>blocknum = <NUM_LIT:0><EOL>if "<STR_LIT>" in headers:<EOL><INDENT>size = int(headers["<STR_LIT>"])<EOL><DEDENT>if reporthook:<EOL><INDENT>reporthook(blocknum, blocksize, size)<EOL><DEDENT>while True:<EOL><INDENT>block = sfp.read(blocksize)<EOL>if not block:<EOL><INDENT>break<EOL><DEDENT>read += len(block)<EOL>dfp.write(block)<EOL>if digester:<EOL><INDENT>digester.update(block)<EOL><DEDENT>blocknum += <NUM_LIT:1><EOL>if reporthook:<EOL><INDENT>reporthook(blocknum, blocksize, size)<EOL><DEDENT><DEDENT><DEDENT>finally:<EOL><INDENT>sfp.close()<EOL><DEDENT><DEDENT>if size >= <NUM_LIT:0> and read < size:<EOL><INDENT>raise DistlibException(<EOL>'<STR_LIT>'<EOL>% (read, size))<EOL><DEDENT>if digester:<EOL><INDENT>actual = digester.hexdigest()<EOL>if digest != actual:<EOL><INDENT>raise DistlibException('<STR_LIT>'<EOL>'<STR_LIT>' % (hasher, destfile,<EOL>digest, actual))<EOL><DEDENT>logger.debug('<STR_LIT>', digest)<EOL><DEDENT>
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.