mailcap.py

来自「mallet是自然语言处理、机器学习领域的一个开源项目。」· Python 代码 · 共 256 行

PY
256
字号
"""Mailcap file handling.  See RFC 1524."""import os__all__ = ["getcaps","findmatch"]# Part 1: top-level interface.def getcaps():    """Return a dictionary containing the mailcap database.    The dictionary maps a MIME type (in all lowercase, e.g. 'text/plain')    to a list of dictionaries corresponding to mailcap entries.  The list    collects all the entries for that MIME type from all available mailcap    files.  Each dictionary contains key-value pairs for that MIME type,    where the viewing command is stored with the key "view".    """    caps = {}    for mailcap in listmailcapfiles():        try:            fp = open(mailcap, 'r')        except IOError:            continue        morecaps = readmailcapfile(fp)        fp.close()        for key in morecaps.keys():            if not caps.has_key(key):                caps[key] = morecaps[key]            else:                caps[key] = caps[key] + morecaps[key]    return capsdef listmailcapfiles():    """Return a list of all mailcap files found on the system."""    # XXX Actually, this is Unix-specific    if os.environ.has_key('MAILCAPS'):        str = os.environ['MAILCAPS']        mailcaps = str.split(':')    else:        if os.environ.has_key('HOME'):            home = os.environ['HOME']        else:            # Don't bother with getpwuid()            home = '.' # Last resort        mailcaps = [home + '/.mailcap', '/etc/mailcap',                '/usr/etc/mailcap', '/usr/local/etc/mailcap']    return mailcaps# Part 2: the parser.def readmailcapfile(fp):    """Read a mailcap file and return a dictionary keyed by MIME type.    Each MIME type is mapped to an entry consisting of a list of    dictionaries; the list will contain more than one such dictionary    if a given MIME type appears more than once in the mailcap file.    Each dictionary contains key-value pairs for that MIME type, where    the viewing command is stored with the key "view".    """    caps = {}    while 1:        line = fp.readline()        if not line: break        # Ignore comments and blank lines        if line[0] == '#' or line.strip() == '':            continue        nextline = line        # Join continuation lines        while nextline[-2:] == '\\\n':            nextline = fp.readline()            if not nextline: nextline = '\n'            line = line[:-2] + nextline        # Parse the line        key, fields = parseline(line)        if not (key and fields):            continue        # Normalize the key        types = key.split('/')        for j in range(len(types)):            types[j] = types[j].strip()        key = '/'.join(types).lower()        # Update the database        if caps.has_key(key):            caps[key].append(fields)        else:            caps[key] = [fields]    return capsdef parseline(line):    """Parse one entry in a mailcap file and return a dictionary.    The viewing command is stored as the value with the key "view",    and the rest of the fields produce key-value pairs in the dict.    """    fields = []    i, n = 0, len(line)    while i < n:        field, i = parsefield(line, i, n)        fields.append(field)        i = i+1 # Skip semicolon    if len(fields) < 2:        return None, None    key, view, rest = fields[0], fields[1], fields[2:]    fields = {'view': view}    for field in rest:        i = field.find('=')        if i < 0:            fkey = field            fvalue = ""        else:            fkey = field[:i].strip()            fvalue = field[i+1:].strip()        if fields.has_key(fkey):            # Ignore it            pass        else:            fields[fkey] = fvalue    return key, fieldsdef parsefield(line, i, n):    """Separate one key-value pair in a mailcap entry."""    start = i    while i < n:        c = line[i]        if c == ';':            break        elif c == '\\':            i = i+2        else:            i = i+1    return line[start:i].strip(), i# Part 3: using the database.def findmatch(caps, MIMEtype, key='view', filename="/dev/null", plist=[]):    """Find a match for a mailcap entry.    Return a tuple containing the command line, and the mailcap entry    used; (None, None) if no match is found.  This may invoke the    'test' command of several matching entries before deciding which    entry to use.    """    entries = lookup(caps, MIMEtype, key)    # XXX This code should somehow check for the needsterminal flag.    for e in entries:        if e.has_key('test'):            test = subst(e['test'], filename, plist)            if test and os.system(test) != 0:                continue        command = subst(e[key], MIMEtype, filename, plist)        return command, e    return None, Nonedef lookup(caps, MIMEtype, key=None):    entries = []    if caps.has_key(MIMEtype):        entries = entries + caps[MIMEtype]    MIMEtypes = MIMEtype.split('/')    MIMEtype = MIMEtypes[0] + '/*'    if caps.has_key(MIMEtype):        entries = entries + caps[MIMEtype]    if key is not None:        entries = filter(lambda e, key=key: e.has_key(key), entries)    return entriesdef subst(field, MIMEtype, filename, plist=[]):    # XXX Actually, this is Unix-specific    res = ''    i, n = 0, len(field)    while i < n:        c = field[i]; i = i+1        if c != '%':            if c == '\\':                c = field[i:i+1]; i = i+1            res = res + c        else:            c = field[i]; i = i+1            if c == '%':                res = res + c            elif c == 's':                res = res + filename            elif c == 't':                res = res + MIMEtype            elif c == '{':                start = i                while i < n and field[i] != '}':                    i = i+1                name = field[start:i]                i = i+1                res = res + findparam(name, plist)            # XXX To do:            # %n == number of parts if type is multipart/*            # %F == list of alternating type and filename for parts            else:                res = res + '%' + c    return resdef findparam(name, plist):    name = name.lower() + '='    n = len(name)    for p in plist:        if p[:n].lower() == name:            return p[n:]    return ''# Part 4: test program.def test():    import sys    caps = getcaps()    if not sys.argv[1:]:        show(caps)        return    for i in range(1, len(sys.argv), 2):        args = sys.argv[i:i+2]        if len(args) < 2:            print "usage: mailcap [MIMEtype file] ..."            return        MIMEtype = args[0]        file = args[1]        command, e = findmatch(caps, MIMEtype, 'view', file)        if not command:            print "No viewer found for", type        else:            print "Executing:", command            sts = os.system(command)            if sts:                print "Exit status:", stsdef show(caps):    print "Mailcap files:"    for fn in listmailcapfiles(): print "\t" + fn    print    if not caps: caps = getcaps()    print "Mailcap entries:"    print    ckeys = caps.keys()    ckeys.sort()    for type in ckeys:        print type        entries = caps[type]        for e in entries:            keys = e.keys()            keys.sort()            for k in keys:                print "  %-15s" % k, e[k]            printif __name__ == '__main__':    test()

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?