human
Complete this python program:
def index_db(index_filename, filenames=None, format=None, alphabet=None, key_function=None):
assistant
#Here is the Python program you requested.

    """Index several sequence files and return a dictionary like object.
    The index is stored in an SQLite database rather than in memory (as in the
    Bio.SeqIO.index(...) function).
    Arguments:
    - index_filename - Where to store the SQLite index
    - filenames - list of strings specifying file(s) to be indexed, or when
    indexing a single file this can be given as a string.
    (optional if reloading an existing index, but must match)
    - format   - lower case string describing the file format
    (optional if reloading an existing index, but must match)
    - alphabet - optional Alphabet object, useful when the sequence type
    cannot be automatically inferred from the file itself
    (e.g. format="fasta" or "tab")
    - key_function - Optional callback function which when given a
    SeqRecord identifier string should return a unique
    key for the dictionary.
    This indexing function will return a dictionary like object, giving the
    SeqRecord objects as values:
    >>> from Bio.Alphabet import generic_protein
    >>> from Bio import SeqIO
    >>> files = ["GenBank/NC_000932.faa", "GenBank/NC_005816.faa"]
    >>> def get_gi(name):
    ...     parts = name.split("|")
    ...     i = parts.index("gi")
    ...     assert i != -1
    ...     return parts[i+1]
    >>> idx_name = ":memory:" #use an in memory SQLite DB for this test
    >>> records = SeqIO.index_db(idx_name, files, "fasta", generic_protein, get_gi)
    >>> len(records)
    95
    >>> records["7525076"].description
    \gi|7525076|ref|NP_051101.1| Ycf2 [Arabidopsis thaliana]\
    >>> records["45478717"].description
    \gi|45478717|ref|NP_995572.1| pesticin [Yersinia pestis biovar Microtus str. 91001]\
    >>> records.close()
    In this example the two files contain 85 and 10 records respectively.
    BGZF compressed files are supported, and detected automatically. Ordinary
    GZIP compressed files are not supported.
    See Also: Bio.SeqIO.index() and Bio.SeqIO.to_dict(), and the Python module
    glob which is useful for..."""
    if (not isinstance(index_filename, basestring)):
        raise TypeError('Need    a    string    for    the    index    filename')
    if isinstance(filenames, basestring):
        filenames = [filenames]
    if ((filenames is not None) and (not isinstance(filenames, list))):
        raise TypeError('Need    a    list    of    filenames    (as    strings),    or    one    filename')
    if ((format is not None) and (not isinstance(format, basestring))):
        raise TypeError('Need    a    string    for    the    file    format    (lower    case)')
    if (format and (format != format.lower())):
        raise ValueError(("Format    string    '%s'    should    be    lower    case" % format))
    if ((alphabet is not None) and (not (isinstance(alphabet, Alphabet) or isinstance(alphabet, AlphabetEncoder)))):
        raise ValueError(('Invalid    alphabet,    %r' % alphabet))
    from ._index import _FormatToRandomAccess
    from Bio.File import _SQLiteManySeqFilesDict
    repr = ('SeqIO.index_db(%r,    filenames=%r,    format=%r,    alphabet=%r,    key_function=%r)' % (index_filename, filenames, format, alphabet, key_function))
    def proxy_factory(format, filename=None):
        'Given    a    filename    returns    proxy    object,    else    boolean    if    format    OK.'
        if filename:
            return _FormatToRandomAccess[format](filename, format, alphabet)
        else:
            return (format in _FormatToRandomAccess)
    return _SQLiteManySeqFilesDict(index_filename, filenames, proxy_factory, format, key_function, repr)