'retrieve(url) returns (filename, headers) for a local object
or (tempfilename, headers) for a remote object.'

def retrieve(self, url, filename=None, reporthook=None, data=None):

    url = unwrap(toBytes(url))
    if (self.tempcache and (url in self.tempcache)):
        return self.tempcache[url]
    (type, url1) = splittype(url)
    if ((filename is None) and ((not type) or (type == 'file'))):
        try:
            fp = self.open_local_file(url1)
            hdrs = fp.info()
            fp.close()
            return (url2pathname(splithost(url1)[1]), hdrs)
        except IOError:
            pass
    fp = self.open(url, data)
    try:
        headers = fp.info()
        if filename:
            tfp = open(filename, 'wb')
        else:
            import tempfile
            (garbage, path) = splittype(url)
            (garbage, path) = splithost((path or ''))
            (path, garbage) = splitquery((path or ''))
            (path, garbage) = splitattr((path or ''))
            suffix = os.path.splitext(path)[1]
            (fd, filename) = tempfile.mkstemp(suffix)
            self.__tempfiles.append(filename)
            tfp = os.fdopen(fd, 'wb')
        try:
            result = (filename, headers)
            if (self.tempcache is not None):
                self.tempcache[url] = result
            bs = (1024 * 8)
            size = (-1)
            read = 0
            blocknum = 0
            if reporthook:
                if ('content-length' in headers):
                    size = int(headers['Content-Length'])
                reporthook(blocknum, bs, size)
            while 1:
                block = fp.read(bs)
                if (block == ''):
                    break
                read += len(block)
                tfp.write(block)
                blocknum += 1
                if reporthook:
                    reporthook(blocknum, bs, size)
        finally:
            tfp.close()
    finally:
        fp.close()
    if ((size >= 0) and (read < size)):
        raise ContentTooShortError(('retrieval    incomplete:    got    only    %i    out    of    %i    bytes' % (read, size)), result)
    return result
