def download(download_info):
    """Module  method for downloading from S3

    This public module method takes a key and the full path to
    the destination directory, assumes that the args have been
    validated by the public caller methods, and attempts to
    download the specified key to the dest_dir.

    :param download_info: (dict) Contains the following params
        key: (str) S3 key for the file to be downloaded
        dest_dir: (str) Full path destination directory
        bucket_name: (str) Name of the bucket to download from
        credentials: (dict) containing AWS credential info (optional)
            aws_region: (str) AWS S3 region
            aws_access_key_id: (str) AWS access key ID
            aws_secret_access_key: (str) AWS secret access key
    :return: (str) Downloaded file destination if the file was
        downloaded successfully
    :raises S3UtilError
    """
    log = logging.getLogger(mod_logger + '.download')

    # Ensure the passed arg is a dict
    if not isinstance(download_info, dict):
        msg = 'download_info arg should be a dict, found: {t}'.format(t=download_info.__class__.__name__)
        raise TypeError(msg)

    # Check for and obtain required args
    required_args = ['key', 'dest_dir', 'bucket_name']
    for required_arg in required_args:
        if required_arg not in download_info:
            msg = 'Required arg not provided: {r}'.format(r=required_arg)
            log.error(msg)
            raise S3UtilError(msg)

    log.debug('Processing download request: {r}'.format(r=download_info))
    key = download_info['key']
    dest_dir = download_info['dest_dir']
    bucket_name = download_info['bucket_name']
    region_name = None
    aws_access_key_id = None
    aws_secret_access_key = None

    try:
        creds = download_info['credentials']
    except KeyError:
        log.debug('No credentials found for this download request')
    else:
        try:
            region_name = creds['region_name']
            aws_access_key_id = creds['aws_access_key_id']
            aws_secret_access_key = creds['aws_secret_access_key']
        except KeyError:
            log.warn('Insufficient credentials found for download request')
            region_name = None
            aws_access_key_id = None
            aws_secret_access_key = None

    log.debug('Configuring S3 client with AWS Access key ID {k} and region {r}'.format(
        k=aws_access_key_id, r=region_name))

    # Establish an S3 client
    client = boto3.client('s3', region_name=region_name, aws_access_key_id=aws_access_key_id,
                          aws_secret_access_key=aws_secret_access_key)

    # Attempt to determine the file name from key
    filename = key.split('/')[-1]
    if filename is None:
        msg = 'Could not determine the filename from key: {k}'.format(k=key)
        log.error(msg)
        raise S3UtilError(msg)

    # Set the destination
    destination = os.path.join(dest_dir, filename)

    # Return if the destination file was already downloaded
    if os.path.isfile(destination):
        log.info('File already downloaded: {d}'.format(d=destination))
        return destination

    # Attempt the download
    log.info('Attempting to download %s from bucket %s to destination %s',
             key, bucket_name, destination)
    max_tries = 10
    retry_timer = 5
    count = 1
    while count <= max_tries:
        log.info('Attempting to download file {k}: try {c} of {m}'.format(k=key, c=count, m=max_tries))
        try:
            client.download_file(Bucket=bucket_name, Key=key, Filename=destination)
        except ClientError:
            if count >= max_tries:
                _, ex, trace = sys.exc_info()
                msg = 'Unable to download key {k} from S3 bucket {b}:\n{e}'.format(k=key, b=bucket_name, e=str(ex))
                log.error(msg)
                raise S3UtilError, msg, trace
            else:
                log.warn('Download failed, re-trying in {t} sec...'.format(t=retry_timer))
                count += 1
                time.sleep(retry_timer)
                continue
        else:
            log.info('Successfully downloaded {k} from S3 bucket {b} to: {d}'.format(
                    k=key, b=bucket_name, d=destination))
            return destination
Module  method for downloading from S3

    This public module method takes a key and the full path to
    the destination directory, assumes that the args have been
    validated by the public caller methods, and attempts to
    download the specified key to the dest_dir.

    :param download_info: (dict) Contains the following params
        key: (str) S3 key for the file to be downloaded
        dest_dir: (str) Full path destination directory
        bucket_name: (str) Name of the bucket to download from
        credentials: (dict) containing AWS credential info (optional)
            aws_region: (str) AWS S3 region
            aws_access_key_id: (str) AWS access key ID
            aws_secret_access_key: (str) AWS secret access key
    :return: (str) Downloaded file destination if the file was
        downloaded successfully
    :raises S3UtilError