def get_cdna_url(species, release=None, ftp=None):
<EOL>assert isinstance(species, (str, _oldstr))<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>if ftp is None:<EOL><INDENT>ftp_server = '<STR_LIT>'<EOL>ftp_user = '<STR_LIT>'<EOL>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>fasta_dir = '<STR_LIT>' % release <EOL>ftp.cwd(fasta_dir)<EOL>if not species in ftp.nlst():<EOL><INDENT>logger.error('<STR_LIT>', species)<EOL>fasta_url = '<STR_LIT>' %(ftp_server, fasta_dir)<EOL>raise ValueError('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>% (species, fasta_url))<EOL><DEDENT>cdna_dir = '<STR_LIT>' %(release, species)<EOL>ftp.cwd(cdna_dir)<EOL>files = ftp.nlst()<EOL>cdna_file = [f for f in files if f.endswith('<STR_LIT>')][<NUM_LIT:0>]<EOL>cdna_url = '<STR_LIT>' %(ftp_server, cdna_dir, cdna_file)<EOL>if close_connection:<EOL><INDENT>ftp.close()<EOL><DEDENT>return cdna_url<EOL>
Returns the URL for a cDNA file hosted on the Ensembl FTP server.

    Parameters
    ----------
    species: str
        The scientific name of the species. It should be all lower-case,
        and the genus and species parts should be separated by an underscore
        (e.g., "homo_sapiens").
    release: int or ``None``, optional
        The Ensembl release number. If ``None``, the latest release is used.
        [None]
    ftp: ftplib.FTP or ``None``, optional
        The FTP connection. If ``None``, create a new connection. [None]