def find_id3v1(fileobj, v2_version=4, known_frames=None):
    """Returns a tuple of (id3tag, offset_to_end) or (None, 0)

    offset mainly because we used to write too short tags in some cases and
    we need the offset to delete them.

    v2_version: Decides whether ID3v2.3 or ID3v2.4 tags
                should be returned. Must be 3 or 4.

    known_frames (Dict[`mutagen.text`, `Frame`]): dict mapping frame
        IDs to Frame objects
    """

    if v2_version not in (3, 4):
        raise ValueError("Only 3 and 4 possible for v2_version")

    # id3v1 is always at the end (after apev2)

    extra_read = b"APETAGEX".index(b"TAG")

    old_pos = fileobj.tell()
    try:
        fileobj.seek(-128 - extra_read, 2)
    except IOError as e:
        if e.errno == errno.EINVAL:
            # If the file is too small, might be ok since we wrote too small
            # tags at some point. let's see how the parsing goes..
            fileobj.seek(0, 0)
        else:
            raise

    data = fileobj.read(128 + extra_read)
    fileobj.seek(old_pos, 0)
    try:
        idx = data.index(b"TAG")
    except ValueError:
        return (None, 0)
    else:
        # FIXME: make use of the apev2 parser here
        # if TAG is part of APETAGEX assume this is an APEv2 tag
        try:
            ape_idx = data.index(b"APETAGEX")
        except ValueError:
            pass
        else:
            if idx == ape_idx + extra_read:
                return (None, 0)

        tag = ParseID3v1(data[idx:], v2_version, known_frames)
        if tag is None:
            return (None, 0)

        offset = idx - len(data)
        return (tag, offset)
def find_id3v1 ( fileobj , v2_version = 4 , known_frames = None ) : if v2_version not in ( 3 , 4 ) : raise ValueError ( "Only 3 and 4 possible for v2_version" ) extra_read = b"APETAGEX" . index ( b"TAG" ) old_pos = fileobj . tell ( ) try : fileobj . seek ( - 128 - extra_read , 2 ) except IOError as e : if e . errno == errno . EINVAL : fileobj . seek ( 0 , 0 ) else : raise data = fileobj . read ( 128 + extra_read ) fileobj . seek ( old_pos , 0 ) try : idx = data . index ( b"TAG" ) except ValueError : return ( None , 0 ) else : try : ape_idx = data . index ( b"APETAGEX" ) except ValueError : pass else : if idx == ape_idx + extra_read : return ( None , 0 ) tag = ParseID3v1 ( data [ idx : ] , v2_version , known_frames ) if tag is None : return ( None , 0 ) offset = idx - len ( data ) return ( tag , offset )
Returns a tuple of (id3tag, offset_to_end) or (None, 0)

    offset mainly because we used to write too short tags in some cases and
    we need the offset to delete them.

    v2_version: Decides whether ID3v2.3 or ID3v2.4 tags
                should be returned. Must be 3 or 4.

    known_frames (Dict[`mutagen.text`, `Frame`]): dict mapping frame
        IDs to Frame objects