def get_annotation_urls_and_checksums(species, release=None, ftp=None):
<EOL>assert isinstance(species, (str, _oldstr)) or isinstance(species, Iterable)<EOL>if release is not None:<EOL><INDENT>assert isinstance(release, int)<EOL><DEDENT>if ftp is not None:<EOL><INDENT>assert isinstance(ftp, ftplib.FTP)<EOL><DEDENT>close_connection = False<EOL>ftp_server = '<STR_LIT>'<EOL>ftp_user = '<STR_LIT>'<EOL>if ftp is None:<EOL><INDENT>ftp = ftplib.FTP(ftp_server)<EOL>ftp.login(ftp_user)<EOL>close_connection = True    <EOL><DEDENT>if release is None:<EOL><INDENT>release = util.get_latest_release(ftp=ftp)<EOL><DEDENT>species_data = OrderedDict()<EOL>if isinstance(species, (str, _oldstr)):<EOL><INDENT>species_list = [species]<EOL><DEDENT>else:<EOL><INDENT>species_list = species<EOL><DEDENT>for spec in species_list:<EOL><INDENT>species_dir = '<STR_LIT>' % (release, spec.lower())<EOL>data = []<EOL>ftp.dir(species_dir, data.append)<EOL>gtf_file = []<EOL>for d in data:<EOL><INDENT>i = d.rindex('<STR_LIT:U+0020>')<EOL>fn = d[(i + <NUM_LIT:1>):]<EOL>if fn.endswith('<STR_LIT>' % release):<EOL><INDENT>gtf_file.append(fn)<EOL><DEDENT><DEDENT>assert len(gtf_file) == <NUM_LIT:1><EOL>gtf_file = gtf_file[<NUM_LIT:0>]<EOL>_LOGGER.debug('<STR_LIT>', gtf_file)<EOL>checksum_url = '<STR_LIT:/>'.join([species_dir, '<STR_LIT>'])<EOL>file_checksums = util.get_file_checksums(checksum_url, ftp=ftp)<EOL>gtf_checksum = file_checksums[gtf_file]<EOL>_LOGGER.debug('<STR_LIT>', gtf_checksum)<EOL>gtf_url = '<STR_LIT>' %(ftp_server, species_dir, gtf_file)<EOL>species_data[spec] = (gtf_url, gtf_checksum)<EOL><DEDENT>if close_connection:<EOL><INDENT>ftp.close()<EOL><DEDENT>return species_data<EOL>
Get FTP URLs and checksums for Ensembl genome annotations.

    Parameters
    ----------
    species : str or list of str
        The species or list of species for which to get genome annotations
        (e.g., "Homo_sapiens").
    release : int, optional
        The release number to look up. If `None`, use latest release. [None]
    ftp : ftplib.FTP, optional
        The FTP connection to use. If `None`, the function will open and close
        its own connection using user "anonymous".