Mercurial > cpython-lru_cache-weakref
annotate Lib/mailcap.py @ 4566:6403c94de50d legacy-trunk
Added safeguard against failure in __del__.
| author | Guido van Rossum <guido@python.org> |
|---|---|
| date | Wed, 27 Nov 1996 19:39:58 +0000 |
| parents | ab43715ef4ee |
| children | 9bf650f23da5 |
| rev | line source |
|---|---|
| 3133 | 1 # Mailcap file handling. See RFC 1524. |
| 2 | |
| 3 import os | |
| 4 import string | |
| 5 import tempfile | |
| 6 | |
| 7 | |
| 8 # Part 1: top-level interface. | |
| 9 | |
| 10 def getcaps(): | |
| 11 caps = {} | |
| 12 for mailcap in listmailcapfiles(): | |
| 13 try: | |
| 14 fp = open(mailcap, 'r') | |
| 15 except: | |
| 16 continue | |
| 17 morecaps = readmailcapfile(fp) | |
| 18 fp.close() | |
| 19 for key in morecaps.keys(): | |
| 20 if not caps.has_key(key): | |
| 21 caps[key] = morecaps[key] | |
| 22 else: | |
| 23 caps[key] = caps[key] + morecaps[key] | |
| 24 return caps | |
| 25 | |
| 26 def listmailcapfiles(): | |
| 27 # XXX Actually, this is Unix-specific | |
| 28 if os.environ.has_key('MAILCAPS'): | |
| 29 str = os.environ['MAILCAPS'] | |
| 30 mailcaps = string.splitfields(str, ':') | |
| 31 else: | |
| 32 if os.environ.has_key('HOME'): | |
| 33 home = os.environ['HOME'] | |
| 34 else: | |
| 35 # Don't bother with getpwuid() | |
| 36 home = '.' # Last resort | |
| 37 mailcaps = [home + '/.mailcap', '/etc/mailcap', | |
| 38 '/usr/etc/mailcap', '/usr/local/etc/mailcap'] | |
| 39 return mailcaps | |
| 40 | |
| 41 | |
| 42 # Part 2: the parser. | |
| 43 | |
| 44 def readmailcapfile(fp): | |
| 45 caps = {} | |
| 46 while 1: | |
| 47 line = fp.readline() | |
| 48 if not line: break | |
| 49 # Ignore comments and blank lines | |
| 50 if line[0] == '#' or string.strip(line) == '': | |
| 51 continue | |
| 52 nextline = line | |
| 53 # Join continuation lines | |
| 54 while nextline[-2:] == '\\\n': | |
| 55 nextline = fp.readline() | |
| 56 if not nextline: nextline = '\n' | |
| 57 line = line[:-2] + nextline | |
| 58 # Parse the line | |
| 59 key, fields = parseline(line) | |
| 60 if not (key and fields): | |
|
4148
ab43715ef4ee
typo (cotinue -> continue)
Guido van Rossum <guido@python.org>
parents:
3133
diff
changeset
|
61 continue |
| 3133 | 62 # Normalize the key |
| 63 types = string.splitfields(key, '/') | |
| 64 for j in range(len(types)): | |
| 65 types[j] = string.strip(types[j]) | |
| 66 key = string.lower(string.joinfields(types, '/')) | |
| 67 # Update the database | |
| 68 if caps.has_key(key): | |
| 69 caps[key].append(fields) | |
| 70 else: | |
| 71 caps[key] = [fields] | |
| 72 return caps | |
| 73 | |
| 74 def parseline(line): | |
| 75 fields = [] | |
| 76 i, n = 0, len(line) | |
| 77 while i < n: | |
| 78 field, i = parsefield(line, i, n) | |
| 79 fields.append(field) | |
| 80 i = i+1 # Skip semicolon | |
| 81 if len(fields) < 2: | |
| 82 return None, None | |
| 83 key, view, rest = fields[0], fields[1], fields[2:] | |
| 84 fields = {'view': view} | |
| 85 for field in rest: | |
| 86 i = string.find(field, '=') | |
| 87 if i < 0: | |
| 88 fkey = field | |
| 89 fvalue = "" | |
| 90 else: | |
| 91 fkey = string.strip(field[:i]) | |
| 92 fvalue = string.strip(field[i+1:]) | |
| 93 if fields.has_key(fkey): | |
| 94 # Ignore it | |
| 95 pass | |
| 96 else: | |
| 97 fields[fkey] = fvalue | |
| 98 return key, fields | |
| 99 | |
| 100 def parsefield(line, i, n): | |
| 101 start = i | |
| 102 while i < n: | |
| 103 c = line[i] | |
| 104 if c == ';': | |
| 105 break | |
| 106 elif c == '\\': | |
| 107 i = i+2 | |
| 108 else: | |
| 109 i = i+1 | |
| 110 return string.strip(line[start:i]), i | |
| 111 | |
| 112 | |
| 113 # Part 3: using the database. | |
| 114 | |
| 115 def findmatch(caps, type, key='view', filename="/dev/null", plist=[]): | |
| 116 entries = lookup(caps, type, key) | |
| 117 for e in entries: | |
| 118 if e.has_key('test'): | |
| 119 test = subst(e['test'], filename, plist) | |
| 120 if test and os.system(test) != 0: | |
| 121 continue | |
| 122 command = subst(e[key], type, filename, plist) | |
| 123 return command, e | |
| 124 return None, None | |
| 125 | |
| 126 def lookup(caps, type, key=None): | |
| 127 entries = [] | |
| 128 if caps.has_key(type): | |
| 129 entries = entries + caps[type] | |
| 130 types = string.splitfields(type, '/') | |
| 131 type = types[0] + '/*' | |
| 132 if caps.has_key(type): | |
| 133 entries = entries + caps[type] | |
| 134 if key is not None: | |
| 135 entries = filter(lambda e, key=key: e.has_key(key), entries) | |
| 136 return entries | |
| 137 | |
| 138 def subst(field, type, filename, plist=[]): | |
| 139 # XXX Actually, this is Unix-specific | |
| 140 res = '' | |
| 141 i, n = 0, len(field) | |
| 142 while i < n: | |
| 143 c = field[i]; i = i+1 | |
| 144 if c <> '%': | |
| 145 if c == '\\': | |
| 146 c = field[i:i+1]; i = i+1 | |
| 147 res = res + c | |
| 148 else: | |
| 149 c = field[i]; i = i+1 | |
| 150 if c == '%': | |
| 151 res = res + c | |
| 152 elif c == 's': | |
| 153 res = res + filename | |
| 154 elif c == 't': | |
| 155 res = res + type | |
| 156 elif c == '{': | |
| 157 start = i | |
| 158 while i < n and field[i] <> '}': | |
| 159 i = i+1 | |
| 160 name = field[start:i] | |
| 161 i = i+1 | |
| 162 res = res + findparam(name, plist) | |
| 163 # XXX To do: | |
| 164 # %n == number of parts if type is multipart/* | |
| 165 # %F == list of alternating type and filename for parts | |
| 166 else: | |
| 167 res = res + '%' + c | |
| 168 return res | |
| 169 | |
| 170 def findparam(name, plist): | |
| 171 name = string.lower(name) + '=' | |
| 172 n = len(name) | |
| 173 for p in plist: | |
| 174 if string.lower(p[:n]) == name: | |
| 175 return p[n:] | |
| 176 return '' | |
| 177 | |
| 178 | |
| 179 # Part 4: test program. | |
| 180 | |
| 181 def test(): | |
| 182 import sys | |
| 183 caps = getcaps() | |
| 184 if not sys.argv[1:]: | |
| 185 show(caps) | |
| 186 return | |
| 187 for i in range(1, len(sys.argv), 2): | |
| 188 args = sys.argv[i:i+2] | |
| 189 if len(args) < 2: | |
| 190 print "usage: mailcap [type file] ..." | |
| 191 return | |
| 192 type = args[0] | |
| 193 file = args[1] | |
| 194 command, e = findmatch(caps, type, 'view', file) | |
| 195 if not command: | |
| 196 print "No viewer found for", type | |
| 197 else: | |
| 198 print "Executing:", command | |
| 199 sts = os.system(command) | |
| 200 if sts: | |
| 201 print "Exit status:", sts | |
| 202 | |
| 203 def show(caps): | |
| 204 print "Mailcap files:" | |
| 205 for fn in listmailcapfiles(): print "\t" + fn | |
| 206 print | |
| 207 if not caps: caps = getcaps() | |
| 208 print "Mailcap entries:" | |
| 209 print | |
| 210 ckeys = caps.keys() | |
| 211 ckeys.sort() | |
| 212 for type in ckeys: | |
| 213 print type | |
| 214 entries = caps[type] | |
| 215 for e in entries: | |
| 216 keys = e.keys() | |
| 217 keys.sort() | |
| 218 for k in keys: | |
| 219 print " %-15s" % k, e[k] | |
| 220 print | |
| 221 | |
| 222 if __name__ == '__main__': | |
| 223 test() |
