diff options
author | Guido van Rossum <guido@python.org> | 1998-03-26 21:13:24 (GMT) |
---|---|---|
committer | Guido van Rossum <guido@python.org> | 1998-03-26 21:13:24 (GMT) |
commit | 45e2fbc2e70ef28b1f0327207f33dab3a4e825c5 (patch) | |
tree | 24cafdb6ffb07170188292a02440935291327cde /Lib/mhlib.py | |
parent | 9ea7024754f0e42d7fc70fd1c8f6f6cfbf7e1cf0 (diff) | |
download | cpython-45e2fbc2e70ef28b1f0327207f33dab3a4e825c5.zip cpython-45e2fbc2e70ef28b1f0327207f33dab3a4e825c5.tar.gz cpython-45e2fbc2e70ef28b1f0327207f33dab3a4e825c5.tar.bz2 |
Mass check-in after untabifying all files that need it.
Diffstat (limited to 'Lib/mhlib.py')
-rw-r--r-- | Lib/mhlib.py | 1216 |
1 files changed, 608 insertions, 608 deletions
diff --git a/Lib/mhlib.py b/Lib/mhlib.py index dc98712..85bf2cd 100644 --- a/Lib/mhlib.py +++ b/Lib/mhlib.py @@ -96,142 +96,142 @@ class MH: # Constructor def __init__(self, path = None, profile = None): - if not profile: profile = MH_PROFILE - self.profile = os.path.expanduser(profile) - if not path: path = self.getprofile('Path') - if not path: path = PATH - if not os.path.isabs(path) and path[0] != '~': - path = os.path.join('~', path) - path = os.path.expanduser(path) - if not os.path.isdir(path): raise Error, 'MH() path not found' - self.path = path + if not profile: profile = MH_PROFILE + self.profile = os.path.expanduser(profile) + if not path: path = self.getprofile('Path') + if not path: path = PATH + if not os.path.isabs(path) and path[0] != '~': + path = os.path.join('~', path) + path = os.path.expanduser(path) + if not os.path.isdir(path): raise Error, 'MH() path not found' + self.path = path # String representation def __repr__(self): - return 'MH(%s, %s)' % (`self.path`, `self.profile`) + return 'MH(%s, %s)' % (`self.path`, `self.profile`) # Routine to print an error. May be overridden by a derived class def error(self, msg, *args): - sys.stderr.write('MH error: %s\n' % (msg % args)) + sys.stderr.write('MH error: %s\n' % (msg % args)) # Return a profile entry, None if not found def getprofile(self, key): - return pickline(self.profile, key) + return pickline(self.profile, key) # Return the path (the name of the collection's directory) def getpath(self): - return self.path + return self.path # Return the name of the current folder def getcontext(self): - context = pickline(os.path.join(self.getpath(), 'context'), - 'Current-Folder') - if not context: context = 'inbox' - return context + context = pickline(os.path.join(self.getpath(), 'context'), + 'Current-Folder') + if not context: context = 'inbox' + return context # Set the name of the current folder def setcontext(self, context): - fn = os.path.join(self.getpath(), 'context') - f = open(fn, "w") - f.write("Current-Folder: %s\n" % context) - f.close() + fn = os.path.join(self.getpath(), 'context') + f = open(fn, "w") + f.write("Current-Folder: %s\n" % context) + f.close() # Return the names of the top-level folders def listfolders(self): - folders = [] - path = self.getpath() - for name in os.listdir(path): - fullname = os.path.join(path, name) - if os.path.isdir(fullname): - folders.append(name) - folders.sort() - return folders + folders = [] + path = self.getpath() + for name in os.listdir(path): + fullname = os.path.join(path, name) + if os.path.isdir(fullname): + folders.append(name) + folders.sort() + return folders # Return the names of the subfolders in a given folder # (prefixed with the given folder name) def listsubfolders(self, name): - fullname = os.path.join(self.path, name) - # Get the link count so we can avoid listing folders - # that have no subfolders. - st = os.stat(fullname) - nlinks = st[ST_NLINK] - if nlinks <= 2: - return [] - subfolders = [] - subnames = os.listdir(fullname) - for subname in subnames: - fullsubname = os.path.join(fullname, subname) - if os.path.isdir(fullsubname): - name_subname = os.path.join(name, subname) - subfolders.append(name_subname) - # Stop looking for subfolders when - # we've seen them all - nlinks = nlinks - 1 - if nlinks <= 2: - break - subfolders.sort() - return subfolders + fullname = os.path.join(self.path, name) + # Get the link count so we can avoid listing folders + # that have no subfolders. + st = os.stat(fullname) + nlinks = st[ST_NLINK] + if nlinks <= 2: + return [] + subfolders = [] + subnames = os.listdir(fullname) + for subname in subnames: + fullsubname = os.path.join(fullname, subname) + if os.path.isdir(fullsubname): + name_subname = os.path.join(name, subname) + subfolders.append(name_subname) + # Stop looking for subfolders when + # we've seen them all + nlinks = nlinks - 1 + if nlinks <= 2: + break + subfolders.sort() + return subfolders # Return the names of all folders, including subfolders, recursively def listallfolders(self): - return self.listallsubfolders('') + return self.listallsubfolders('') # Return the names of subfolders in a given folder, recursively def listallsubfolders(self, name): - fullname = os.path.join(self.path, name) - # Get the link count so we can avoid listing folders - # that have no subfolders. - st = os.stat(fullname) - nlinks = st[ST_NLINK] - if nlinks <= 2: - return [] - subfolders = [] - subnames = os.listdir(fullname) - for subname in subnames: - if subname[0] == ',' or isnumeric(subname): continue - fullsubname = os.path.join(fullname, subname) - if os.path.isdir(fullsubname): - name_subname = os.path.join(name, subname) - subfolders.append(name_subname) - if not os.path.islink(fullsubname): - subsubfolders = self.listallsubfolders( - name_subname) - subfolders = subfolders + subsubfolders - # Stop looking for subfolders when - # we've seen them all - nlinks = nlinks - 1 - if nlinks <= 2: - break - subfolders.sort() - return subfolders + fullname = os.path.join(self.path, name) + # Get the link count so we can avoid listing folders + # that have no subfolders. + st = os.stat(fullname) + nlinks = st[ST_NLINK] + if nlinks <= 2: + return [] + subfolders = [] + subnames = os.listdir(fullname) + for subname in subnames: + if subname[0] == ',' or isnumeric(subname): continue + fullsubname = os.path.join(fullname, subname) + if os.path.isdir(fullsubname): + name_subname = os.path.join(name, subname) + subfolders.append(name_subname) + if not os.path.islink(fullsubname): + subsubfolders = self.listallsubfolders( + name_subname) + subfolders = subfolders + subsubfolders + # Stop looking for subfolders when + # we've seen them all + nlinks = nlinks - 1 + if nlinks <= 2: + break + subfolders.sort() + return subfolders # Return a new Folder object for the named folder def openfolder(self, name): - return Folder(self, name) + return Folder(self, name) # Create a new folder. This raises os.error if the folder # cannot be created def makefolder(self, name): - protect = pickline(self.profile, 'Folder-Protect') - if protect and isnumeric(protect): - mode = string.atoi(protect, 8) - else: - mode = FOLDER_PROTECT - os.mkdir(os.path.join(self.getpath(), name), mode) + protect = pickline(self.profile, 'Folder-Protect') + if protect and isnumeric(protect): + mode = string.atoi(protect, 8) + else: + mode = FOLDER_PROTECT + os.mkdir(os.path.join(self.getpath(), name), mode) # Delete a folder. This removes files in the folder but not # subdirectories. If deleting the folder itself fails it # raises os.error def deletefolder(self, name): - fullname = os.path.join(self.getpath(), name) - for subname in os.listdir(fullname): - fullsubname = os.path.join(fullname, subname) - try: - os.unlink(fullsubname) - except os.error: - self.error('%s not deleted, continuing...' % - fullsubname) - os.rmdir(fullname) + fullname = os.path.join(self.getpath(), name) + for subname in os.listdir(fullname): + fullsubname = os.path.join(fullname, subname) + try: + os.unlink(fullsubname) + except os.error: + self.error('%s not deleted, continuing...' % + fullsubname) + os.rmdir(fullname) # Class representing a particular folder @@ -244,522 +244,522 @@ class Folder: # Constructor def __init__(self, mh, name): - self.mh = mh - self.name = name - if not os.path.isdir(self.getfullname()): - raise Error, 'no folder %s' % name + self.mh = mh + self.name = name + if not os.path.isdir(self.getfullname()): + raise Error, 'no folder %s' % name # String representation def __repr__(self): - return 'Folder(%s, %s)' % (`self.mh`, `self.name`) + return 'Folder(%s, %s)' % (`self.mh`, `self.name`) # Error message handler def error(self, *args): - apply(self.mh.error, args) + apply(self.mh.error, args) # Return the full pathname of the folder def getfullname(self): - return os.path.join(self.mh.path, self.name) + return os.path.join(self.mh.path, self.name) # Return the full pathname of the folder's sequences file def getsequencesfilename(self): - return os.path.join(self.getfullname(), MH_SEQUENCES) + return os.path.join(self.getfullname(), MH_SEQUENCES) # Return the full pathname of a message in the folder def getmessagefilename(self, n): - return os.path.join(self.getfullname(), str(n)) + return os.path.join(self.getfullname(), str(n)) # Return list of direct subfolders def listsubfolders(self): - return self.mh.listsubfolders(self.name) + return self.mh.listsubfolders(self.name) # Return list of all subfolders def listallsubfolders(self): - return self.mh.listallsubfolders(self.name) + return self.mh.listallsubfolders(self.name) # Return the list of messages currently present in the folder. # As a side effect, set self.last to the last message (or 0) def listmessages(self): - messages = [] - match = numericprog.match - append = messages.append - for name in os.listdir(self.getfullname()): - if match(name) >= 0: - append(name) - messages = map(string.atoi, messages) - messages.sort() - if messages: - self.last = messages[-1] - else: - self.last = 0 - return messages + messages = [] + match = numericprog.match + append = messages.append + for name in os.listdir(self.getfullname()): + if match(name) >= 0: + append(name) + messages = map(string.atoi, messages) + messages.sort() + if messages: + self.last = messages[-1] + else: + self.last = 0 + return messages # Return the set of sequences for the folder def getsequences(self): - sequences = {} - fullname = self.getsequencesfilename() - try: - f = open(fullname, 'r') - except IOError: - return sequences - while 1: - line = f.readline() - if not line: break - fields = string.splitfields(line, ':') - if len(fields) <> 2: - self.error('bad sequence in %s: %s' % - (fullname, string.strip(line))) - key = string.strip(fields[0]) - value = IntSet(string.strip(fields[1]), ' ').tolist() - sequences[key] = value - return sequences + sequences = {} + fullname = self.getsequencesfilename() + try: + f = open(fullname, 'r') + except IOError: + return sequences + while 1: + line = f.readline() + if not line: break + fields = string.splitfields(line, ':') + if len(fields) <> 2: + self.error('bad sequence in %s: %s' % + (fullname, string.strip(line))) + key = string.strip(fields[0]) + value = IntSet(string.strip(fields[1]), ' ').tolist() + sequences[key] = value + return sequences # Write the set of sequences back to the folder def putsequences(self, sequences): - fullname = self.getsequencesfilename() - f = None - for key in sequences.keys(): - s = IntSet('', ' ') - s.fromlist(sequences[key]) - if not f: f = open(fullname, 'w') - f.write('%s: %s\n' % (key, s.tostring())) - if not f: - try: - os.unlink(fullname) - except os.error: - pass - else: - f.close() + fullname = self.getsequencesfilename() + f = None + for key in sequences.keys(): + s = IntSet('', ' ') + s.fromlist(sequences[key]) + if not f: f = open(fullname, 'w') + f.write('%s: %s\n' % (key, s.tostring())) + if not f: + try: + os.unlink(fullname) + except os.error: + pass + else: + f.close() # Return the current message. Raise KeyError when there is none def getcurrent(self): - seqs = self.getsequences() - try: - return max(seqs['cur']) - except (ValueError, KeyError): - raise Error, "no cur message" + seqs = self.getsequences() + try: + return max(seqs['cur']) + except (ValueError, KeyError): + raise Error, "no cur message" # Set the current message def setcurrent(self, n): - updateline(self.getsequencesfilename(), 'cur', str(n), 0) + updateline(self.getsequencesfilename(), 'cur', str(n), 0) # Parse an MH sequence specification into a message list. # Attempt to mimic mh-sequence(5) as close as possible. # Also attempt to mimic observed behavior regarding which # conditions cause which error messages def parsesequence(self, seq): - # XXX Still not complete (see mh-format(5)). - # Missing are: - # - 'prev', 'next' as count - # - Sequence-Negation option - all = self.listmessages() - # Observed behavior: test for empty folder is done first - if not all: - raise Error, "no messages in %s" % self.name - # Common case first: all is frequently the default - if seq == 'all': - return all - # Test for X:Y before X-Y because 'seq:-n' matches both - i = string.find(seq, ':') - if i >= 0: - head, dir, tail = seq[:i], '', seq[i+1:] - if tail[:1] in '-+': - dir, tail = tail[:1], tail[1:] - if not isnumeric(tail): - raise Error, "bad message list %s" % seq - try: - count = string.atoi(tail) - except (ValueError, OverflowError): - # Can't use sys.maxint because of i+count below - count = len(all) - try: - anchor = self._parseindex(head, all) - except Error, msg: - seqs = self.getsequences() - if not seqs.has_key(head): - if not msg: - msg = "bad message list %s" % seq - raise Error, msg, sys.exc_info()[2] - msgs = seqs[head] - if not msgs: - raise Error, "sequence %s empty" % head - if dir == '-': - return msgs[-count:] - else: - return msgs[:count] - else: - if not dir: - if head in ('prev', 'last'): - dir = '-' - if dir == '-': - i = bisect(all, anchor) - return all[max(0, i-count):i] - else: - i = bisect(all, anchor-1) - return all[i:i+count] - # Test for X-Y next - i = string.find(seq, '-') - if i >= 0: - begin = self._parseindex(seq[:i], all) - end = self._parseindex(seq[i+1:], all) - i = bisect(all, begin-1) - j = bisect(all, end) - r = all[i:j] - if not r: - raise Error, "bad message list %s" % seq - return r - # Neither X:Y nor X-Y; must be a number or a (pseudo-)sequence - try: - n = self._parseindex(seq, all) - except Error, msg: - seqs = self.getsequences() - if not seqs.has_key(seq): - if not msg: - msg = "bad message list %s" % seq - raise Error, msg - return seqs[seq] - else: - if n not in all: - if isnumeric(seq): - raise Error, "message %d doesn't exist" % n - else: - raise Error, "no %s message" % seq - else: - return [n] + # XXX Still not complete (see mh-format(5)). + # Missing are: + # - 'prev', 'next' as count + # - Sequence-Negation option + all = self.listmessages() + # Observed behavior: test for empty folder is done first + if not all: + raise Error, "no messages in %s" % self.name + # Common case first: all is frequently the default + if seq == 'all': + return all + # Test for X:Y before X-Y because 'seq:-n' matches both + i = string.find(seq, ':') + if i >= 0: + head, dir, tail = seq[:i], '', seq[i+1:] + if tail[:1] in '-+': + dir, tail = tail[:1], tail[1:] + if not isnumeric(tail): + raise Error, "bad message list %s" % seq + try: + count = string.atoi(tail) + except (ValueError, OverflowError): + # Can't use sys.maxint because of i+count below + count = len(all) + try: + anchor = self._parseindex(head, all) + except Error, msg: + seqs = self.getsequences() + if not seqs.has_key(head): + if not msg: + msg = "bad message list %s" % seq + raise Error, msg, sys.exc_info()[2] + msgs = seqs[head] + if not msgs: + raise Error, "sequence %s empty" % head + if dir == '-': + return msgs[-count:] + else: + return msgs[:count] + else: + if not dir: + if head in ('prev', 'last'): + dir = '-' + if dir == '-': + i = bisect(all, anchor) + return all[max(0, i-count):i] + else: + i = bisect(all, anchor-1) + return all[i:i+count] + # Test for X-Y next + i = string.find(seq, '-') + if i >= 0: + begin = self._parseindex(seq[:i], all) + end = self._parseindex(seq[i+1:], all) + i = bisect(all, begin-1) + j = bisect(all, end) + r = all[i:j] + if not r: + raise Error, "bad message list %s" % seq + return r + # Neither X:Y nor X-Y; must be a number or a (pseudo-)sequence + try: + n = self._parseindex(seq, all) + except Error, msg: + seqs = self.getsequences() + if not seqs.has_key(seq): + if not msg: + msg = "bad message list %s" % seq + raise Error, msg + return seqs[seq] + else: + if n not in all: + if isnumeric(seq): + raise Error, "message %d doesn't exist" % n + else: + raise Error, "no %s message" % seq + else: + return [n] # Internal: parse a message number (or cur, first, etc.) def _parseindex(self, seq, all): - if isnumeric(seq): - try: - return string.atoi(seq) - except (OverflowError, ValueError): - return sys.maxint - if seq in ('cur', '.'): - return self.getcurrent() - if seq == 'first': - return all[0] - if seq == 'last': - return all[-1] - if seq == 'next': - n = self.getcurrent() - i = bisect(all, n) - try: - return all[i] - except IndexError: - raise Error, "no next message" - if seq == 'prev': - n = self.getcurrent() - i = bisect(all, n-1) - if i == 0: - raise Error, "no prev message" - try: - return all[i-1] - except IndexError: - raise Error, "no prev message" - raise Error, None + if isnumeric(seq): + try: + return string.atoi(seq) + except (OverflowError, ValueError): + return sys.maxint + if seq in ('cur', '.'): + return self.getcurrent() + if seq == 'first': + return all[0] + if seq == 'last': + return all[-1] + if seq == 'next': + n = self.getcurrent() + i = bisect(all, n) + try: + return all[i] + except IndexError: + raise Error, "no next message" + if seq == 'prev': + n = self.getcurrent() + i = bisect(all, n-1) + if i == 0: + raise Error, "no prev message" + try: + return all[i-1] + except IndexError: + raise Error, "no prev message" + raise Error, None # Open a message -- returns a Message object def openmessage(self, n): - return Message(self, n) + return Message(self, n) # Remove one or more messages -- may raise os.error def removemessages(self, list): - errors = [] - deleted = [] - for n in list: - path = self.getmessagefilename(n) - commapath = self.getmessagefilename(',' + str(n)) - try: - os.unlink(commapath) - except os.error: - pass - try: - os.rename(path, commapath) - except os.error, msg: - errors.append(msg) - else: - deleted.append(n) - if deleted: - self.removefromallsequences(deleted) - if errors: - if len(errors) == 1: - raise os.error, errors[0] - else: - raise os.error, ('multiple errors:', errors) + errors = [] + deleted = [] + for n in list: + path = self.getmessagefilename(n) + commapath = self.getmessagefilename(',' + str(n)) + try: + os.unlink(commapath) + except os.error: + pass + try: + os.rename(path, commapath) + except os.error, msg: + errors.append(msg) + else: + deleted.append(n) + if deleted: + self.removefromallsequences(deleted) + if errors: + if len(errors) == 1: + raise os.error, errors[0] + else: + raise os.error, ('multiple errors:', errors) # Refile one or more messages -- may raise os.error. # 'tofolder' is an open folder object def refilemessages(self, list, tofolder, keepsequences=0): - errors = [] - refiled = {} - for n in list: - ton = tofolder.getlast() + 1 - path = self.getmessagefilename(n) - topath = tofolder.getmessagefilename(ton) - try: - os.rename(path, topath) - except os.error: - # Try copying - try: - shutil.copy2(path, topath) - os.unlink(path) - except (IOError, os.error), msg: - errors.append(msg) - try: - os.unlink(topath) - except os.error: - pass - continue - tofolder.setlast(ton) - refiled[n] = ton - if refiled: - if keepsequences: - tofolder._copysequences(self, refiled.items()) - self.removefromallsequences(refiled.keys()) - if errors: - if len(errors) == 1: - raise os.error, errors[0] - else: - raise os.error, ('multiple errors:', errors) + errors = [] + refiled = {} + for n in list: + ton = tofolder.getlast() + 1 + path = self.getmessagefilename(n) + topath = tofolder.getmessagefilename(ton) + try: + os.rename(path, topath) + except os.error: + # Try copying + try: + shutil.copy2(path, topath) + os.unlink(path) + except (IOError, os.error), msg: + errors.append(msg) + try: + os.unlink(topath) + except os.error: + pass + continue + tofolder.setlast(ton) + refiled[n] = ton + if refiled: + if keepsequences: + tofolder._copysequences(self, refiled.items()) + self.removefromallsequences(refiled.keys()) + if errors: + if len(errors) == 1: + raise os.error, errors[0] + else: + raise os.error, ('multiple errors:', errors) # Helper for refilemessages() to copy sequences def _copysequences(self, fromfolder, refileditems): - fromsequences = fromfolder.getsequences() - tosequences = self.getsequences() - changed = 0 - for name, seq in fromsequences.items(): - try: - toseq = tosequences[name] - new = 0 - except: - toseq = [] - new = 1 - for fromn, ton in refileditems: - if fromn in seq: - toseq.append(ton) - changed = 1 - if new and toseq: - tosequences[name] = toseq - if changed: - self.putsequences(tosequences) + fromsequences = fromfolder.getsequences() + tosequences = self.getsequences() + changed = 0 + for name, seq in fromsequences.items(): + try: + toseq = tosequences[name] + new = 0 + except: + toseq = [] + new = 1 + for fromn, ton in refileditems: + if fromn in seq: + toseq.append(ton) + changed = 1 + if new and toseq: + tosequences[name] = toseq + if changed: + self.putsequences(tosequences) # Move one message over a specific destination message, # which may or may not already exist. def movemessage(self, n, tofolder, ton): - path = self.getmessagefilename(n) - # Open it to check that it exists - f = open(path) - f.close() - del f - topath = tofolder.getmessagefilename(ton) - backuptopath = tofolder.getmessagefilename(',%d' % ton) - try: - os.rename(topath, backuptopath) - except os.error: - pass - try: - os.rename(path, topath) - except os.error: - # Try copying - ok = 0 - try: - tofolder.setlast(None) - shutil.copy2(path, topath) - ok = 1 - finally: - if not ok: - try: - os.unlink(topath) - except os.error: - pass - os.unlink(path) - self.removefromallsequences([n]) + path = self.getmessagefilename(n) + # Open it to check that it exists + f = open(path) + f.close() + del f + topath = tofolder.getmessagefilename(ton) + backuptopath = tofolder.getmessagefilename(',%d' % ton) + try: + os.rename(topath, backuptopath) + except os.error: + pass + try: + os.rename(path, topath) + except os.error: + # Try copying + ok = 0 + try: + tofolder.setlast(None) + shutil.copy2(path, topath) + ok = 1 + finally: + if not ok: + try: + os.unlink(topath) + except os.error: + pass + os.unlink(path) + self.removefromallsequences([n]) # Copy one message over a specific destination message, # which may or may not already exist. def copymessage(self, n, tofolder, ton): - path = self.getmessagefilename(n) - # Open it to check that it exists - f = open(path) - f.close() - del f - topath = tofolder.getmessagefilename(ton) - backuptopath = tofolder.getmessagefilename(',%d' % ton) - try: - os.rename(topath, backuptopath) - except os.error: - pass - ok = 0 - try: - tofolder.setlast(None) - shutil.copy2(path, topath) - ok = 1 - finally: - if not ok: - try: - os.unlink(topath) - except os.error: - pass + path = self.getmessagefilename(n) + # Open it to check that it exists + f = open(path) + f.close() + del f + topath = tofolder.getmessagefilename(ton) + backuptopath = tofolder.getmessagefilename(',%d' % ton) + try: + os.rename(topath, backuptopath) + except os.error: + pass + ok = 0 + try: + tofolder.setlast(None) + shutil.copy2(path, topath) + ok = 1 + finally: + if not ok: + try: + os.unlink(topath) + except os.error: + pass # Create a message, with text from the open file txt. def createmessage(self, n, txt): - path = self.getmessagefilename(n) - backuppath = self.getmessagefilename(',%d' % n) - try: - os.rename(path, backuppath) - except os.error: - pass - ok = 0 - BUFSIZE = 16*1024 - try: - f = open(path, "w") - while 1: - buf = txt.read(BUFSIZE) - if not buf: - break - f.write(buf) - f.close() - ok = 1 - finally: - if not ok: - try: - os.unlink(path) - except os.error: - pass + path = self.getmessagefilename(n) + backuppath = self.getmessagefilename(',%d' % n) + try: + os.rename(path, backuppath) + except os.error: + pass + ok = 0 + BUFSIZE = 16*1024 + try: + f = open(path, "w") + while 1: + buf = txt.read(BUFSIZE) + if not buf: + break + f.write(buf) + f.close() + ok = 1 + finally: + if not ok: + try: + os.unlink(path) + except os.error: + pass # Remove one or more messages from all sequeuces (including last) # -- but not from 'cur'!!! def removefromallsequences(self, list): - if hasattr(self, 'last') and self.last in list: - del self.last - sequences = self.getsequences() - changed = 0 - for name, seq in sequences.items(): - if name == 'cur': - continue - for n in list: - if n in seq: - seq.remove(n) - changed = 1 - if not seq: - del sequences[name] - if changed: - self.putsequences(sequences) + if hasattr(self, 'last') and self.last in list: + del self.last + sequences = self.getsequences() + changed = 0 + for name, seq in sequences.items(): + if name == 'cur': + continue + for n in list: + if n in seq: + seq.remove(n) + changed = 1 + if not seq: + del sequences[name] + if changed: + self.putsequences(sequences) # Return the last message number def getlast(self): - if not hasattr(self, 'last'): - messages = self.listmessages() - return self.last + if not hasattr(self, 'last'): + messages = self.listmessages() + return self.last # Set the last message number def setlast(self, last): - if last is None: - if hasattr(self, 'last'): - del self.last - else: - self.last = last + if last is None: + if hasattr(self, 'last'): + del self.last + else: + self.last = last class Message(mimetools.Message): # Constructor def __init__(self, f, n, fp = None): - self.folder = f - self.number = n - if not fp: - path = f.getmessagefilename(n) - fp = open(path, 'r') - mimetools.Message.__init__(self, fp) + self.folder = f + self.number = n + if not fp: + path = f.getmessagefilename(n) + fp = open(path, 'r') + mimetools.Message.__init__(self, fp) # String representation def __repr__(self): - return 'Message(%s, %s)' % (repr(self.folder), self.number) + return 'Message(%s, %s)' % (repr(self.folder), self.number) # Return the message's header text as a string. If an # argument is specified, it is used as a filter predicate to # decide which headers to return (its argument is the header # name converted to lower case). def getheadertext(self, pred = None): - if not pred: - return string.joinfields(self.headers, '') - headers = [] - hit = 0 - for line in self.headers: - if line[0] not in string.whitespace: - i = string.find(line, ':') - if i > 0: - hit = pred(string.lower(line[:i])) - if hit: headers.append(line) - return string.joinfields(headers, '') + if not pred: + return string.joinfields(self.headers, '') + headers = [] + hit = 0 + for line in self.headers: + if line[0] not in string.whitespace: + i = string.find(line, ':') + if i > 0: + hit = pred(string.lower(line[:i])) + if hit: headers.append(line) + return string.joinfields(headers, '') # Return the message's body text as string. This undoes a # Content-Transfer-Encoding, but does not interpret other MIME # features (e.g. multipart messages). To suppress to # decoding, pass a 0 as argument def getbodytext(self, decode = 1): - self.fp.seek(self.startofbody) - encoding = self.getencoding() - if not decode or encoding in ('7bit', '8bit', 'binary'): - return self.fp.read() - from StringIO import StringIO - output = StringIO() - mimetools.decode(self.fp, output, encoding) - return output.getvalue() + self.fp.seek(self.startofbody) + encoding = self.getencoding() + if not decode or encoding in ('7bit', '8bit', 'binary'): + return self.fp.read() + from StringIO import StringIO + output = StringIO() + mimetools.decode(self.fp, output, encoding) + return output.getvalue() # Only for multipart messages: return the message's body as a # list of SubMessage objects. Each submessage object behaves # (almost) as a Message object. def getbodyparts(self): - if self.getmaintype() != 'multipart': - raise Error, 'Content-Type is not multipart/*' - bdry = self.getparam('boundary') - if not bdry: - raise Error, 'multipart/* without boundary param' - self.fp.seek(self.startofbody) - mf = multifile.MultiFile(self.fp) - mf.push(bdry) - parts = [] - while mf.next(): - n = str(self.number) + '.' + `1 + len(parts)` - part = SubMessage(self.folder, n, mf) - parts.append(part) - mf.pop() - return parts + if self.getmaintype() != 'multipart': + raise Error, 'Content-Type is not multipart/*' + bdry = self.getparam('boundary') + if not bdry: + raise Error, 'multipart/* without boundary param' + self.fp.seek(self.startofbody) + mf = multifile.MultiFile(self.fp) + mf.push(bdry) + parts = [] + while mf.next(): + n = str(self.number) + '.' + `1 + len(parts)` + part = SubMessage(self.folder, n, mf) + parts.append(part) + mf.pop() + return parts # Return body, either a string or a list of messages def getbody(self): - if self.getmaintype() == 'multipart': - return self.getbodyparts() - else: - return self.getbodytext() + if self.getmaintype() == 'multipart': + return self.getbodyparts() + else: + return self.getbodytext() class SubMessage(Message): # Constructor def __init__(self, f, n, fp): - Message.__init__(self, f, n, fp) - if self.getmaintype() == 'multipart': - self.body = Message.getbodyparts(self) - else: - self.body = Message.getbodytext(self) - # XXX If this is big, should remember file pointers + Message.__init__(self, f, n, fp) + if self.getmaintype() == 'multipart': + self.body = Message.getbodyparts(self) + else: + self.body = Message.getbodytext(self) + # XXX If this is big, should remember file pointers # String representation def __repr__(self): - f, n, fp = self.folder, self.number, self.fp - return 'SubMessage(%s, %s, %s)' % (f, n, fp) + f, n, fp = self.folder, self.number, self.fp + return 'SubMessage(%s, %s, %s)' % (f, n, fp) def getbodytext(self): - if type(self.body) == type(''): - return self.body + if type(self.body) == type(''): + return self.body def getbodyparts(self): - if type(self.body) == type([]): - return self.body + if type(self.body) == type([]): + return self.body def getbody(self): - return self.body + return self.body # Class implementing sets of integers. @@ -786,169 +786,169 @@ class SubMessage(Message): class IntSet: def __init__(self, data = None, sep = ',', rng = '-'): - self.pairs = [] - self.sep = sep - self.rng = rng - if data: self.fromstring(data) + self.pairs = [] + self.sep = sep + self.rng = rng + if data: self.fromstring(data) def reset(self): - self.pairs = [] + self.pairs = [] def __cmp__(self, other): - return cmp(self.pairs, other.pairs) + return cmp(self.pairs, other.pairs) def __hash__(self): - return hash(self.pairs) + return hash(self.pairs) def __repr__(self): - return 'IntSet(%s, %s, %s)' % (`self.tostring()`, - `self.sep`, `self.rng`) + return 'IntSet(%s, %s, %s)' % (`self.tostring()`, + `self.sep`, `self.rng`) def normalize(self): - self.pairs.sort() - i = 1 - while i < len(self.pairs): - alo, ahi = self.pairs[i-1] - blo, bhi = self.pairs[i] - if ahi >= blo-1: - self.pairs[i-1:i+1] = [(alo, max(ahi, bhi))] - else: - i = i+1 + self.pairs.sort() + i = 1 + while i < len(self.pairs): + alo, ahi = self.pairs[i-1] + blo, bhi = self.pairs[i] + if ahi >= blo-1: + self.pairs[i-1:i+1] = [(alo, max(ahi, bhi))] + else: + i = i+1 def tostring(self): - s = '' - for lo, hi in self.pairs: - if lo == hi: t = `lo` - else: t = `lo` + self.rng + `hi` - if s: s = s + (self.sep + t) - else: s = t - return s + s = '' + for lo, hi in self.pairs: + if lo == hi: t = `lo` + else: t = `lo` + self.rng + `hi` + if s: s = s + (self.sep + t) + else: s = t + return s def tolist(self): - l = [] - for lo, hi in self.pairs: - m = range(lo, hi+1) - l = l + m - return l + l = [] + for lo, hi in self.pairs: + m = range(lo, hi+1) + l = l + m + return l def fromlist(self, list): - for i in list: - self.append(i) + for i in list: + self.append(i) def clone(self): - new = IntSet() - new.pairs = self.pairs[:] - return new + new = IntSet() + new.pairs = self.pairs[:] + return new def min(self): - return self.pairs[0][0] + return self.pairs[0][0] def max(self): - return self.pairs[-1][-1] + return self.pairs[-1][-1] def contains(self, x): - for lo, hi in self.pairs: - if lo <= x <= hi: return 1 - return 0 + for lo, hi in self.pairs: + if lo <= x <= hi: return 1 + return 0 def append(self, x): - for i in range(len(self.pairs)): - lo, hi = self.pairs[i] - if x < lo: # Need to insert before - if x+1 == lo: - self.pairs[i] = (x, hi) - else: - self.pairs.insert(i, (x, x)) - if i > 0 and x-1 == self.pairs[i-1][1]: - # Merge with previous - self.pairs[i-1:i+1] = [ - (self.pairs[i-1][0], - self.pairs[i][1]) - ] - return - if x <= hi: # Already in set - return - i = len(self.pairs) - 1 - if i >= 0: - lo, hi = self.pairs[i] - if x-1 == hi: - self.pairs[i] = lo, x - return - self.pairs.append((x, x)) + for i in range(len(self.pairs)): + lo, hi = self.pairs[i] + if x < lo: # Need to insert before + if x+1 == lo: + self.pairs[i] = (x, hi) + else: + self.pairs.insert(i, (x, x)) + if i > 0 and x-1 == self.pairs[i-1][1]: + # Merge with previous + self.pairs[i-1:i+1] = [ + (self.pairs[i-1][0], + self.pairs[i][1]) + ] + return + if x <= hi: # Already in set + return + i = len(self.pairs) - 1 + if i >= 0: + lo, hi = self.pairs[i] + if x-1 == hi: + self.pairs[i] = lo, x + return + self.pairs.append((x, x)) def addpair(self, xlo, xhi): - if xlo > xhi: return - self.pairs.append((xlo, xhi)) - self.normalize() + if xlo > xhi: return + self.pairs.append((xlo, xhi)) + self.normalize() def fromstring(self, data): - import string - new = [] - for part in string.splitfields(data, self.sep): - list = [] - for subp in string.splitfields(part, self.rng): - s = string.strip(subp) - list.append(string.atoi(s)) - if len(list) == 1: - new.append((list[0], list[0])) - elif len(list) == 2 and list[0] <= list[1]: - new.append((list[0], list[1])) - else: - raise ValueError, 'bad data passed to IntSet' - self.pairs = self.pairs + new - self.normalize() + import string + new = [] + for part in string.splitfields(data, self.sep): + list = [] + for subp in string.splitfields(part, self.rng): + s = string.strip(subp) + list.append(string.atoi(s)) + if len(list) == 1: + new.append((list[0], list[0])) + elif len(list) == 2 and list[0] <= list[1]: + new.append((list[0], list[1])) + else: + raise ValueError, 'bad data passed to IntSet' + self.pairs = self.pairs + new + self.normalize() # Subroutines to read/write entries in .mh_profile and .mh_sequences def pickline(file, key, casefold = 1): try: - f = open(file, 'r') + f = open(file, 'r') except IOError: - return None + return None pat = re.escape(key) + ':' prog = re.compile(pat, casefold and re.IGNORECASE) while 1: - line = f.readline() - if not line: break - if prog.match(line): - text = line[len(key)+1:] - while 1: - line = f.readline() - if not line or line[0] not in string.whitespace: - break - text = text + line - return string.strip(text) + line = f.readline() + if not line: break + if prog.match(line): + text = line[len(key)+1:] + while 1: + line = f.readline() + if not line or line[0] not in string.whitespace: + break + text = text + line + return string.strip(text) return None def updateline(file, key, value, casefold = 1): try: - f = open(file, 'r') - lines = f.readlines() - f.close() + f = open(file, 'r') + lines = f.readlines() + f.close() except IOError: - lines = [] + lines = [] pat = re.escape(key) + ':(.*)\n' prog = re.compile(pat, casefold and re.IGNORECASE) if value is None: - newline = None + newline = None else: - newline = '%s: %s\n' % (key, value) + newline = '%s: %s\n' % (key, value) for i in range(len(lines)): - line = lines[i] - if prog.match(line): - if newline is None: - del lines[i] - else: - lines[i] = newline - break + line = lines[i] + if prog.match(line): + if newline is None: + del lines[i] + else: + lines[i] = newline + break else: - if newline is not None: - lines.append(newline) + if newline is not None: + lines.append(newline) tempfile = file + "~" f = open(tempfile, 'w') for line in lines: - f.write(line) + f.write(line) f.close() os.rename(tempfile, file) @@ -963,8 +963,8 @@ def test(): do('mh.listfolders()') do('mh.listallfolders()') testfolders = ['@test', '@test/test1', '@test/test2', - '@test/test1/test11', '@test/test1/test12', - '@test/test1/test11/test111'] + '@test/test1/test11', '@test/test1/test12', + '@test/test1/test11/test111'] for t in testfolders: do('mh.makefolder(%s)' % `t`) do('mh.listsubfolders(\'@test\')') do('mh.listallsubfolders(\'@test\')') @@ -984,17 +984,17 @@ def test(): f = mh.openfolder(context) do('f.getcurrent()') for seq in ['first', 'last', 'cur', '.', 'prev', 'next', - 'first:3', 'last:3', 'cur:3', 'cur:-3', - 'prev:3', 'next:3', - '1:3', '1:-3', '100:3', '100:-3', '10000:3', '10000:-3', - 'all']: - try: - do('f.parsesequence(%s)' % `seq`) - except Error, msg: - print "Error:", msg - stuff = os.popen("pick %s 2>/dev/null" % `seq`).read() - list = map(string.atoi, string.split(stuff)) - print list, "<-- pick" + 'first:3', 'last:3', 'cur:3', 'cur:-3', + 'prev:3', 'next:3', + '1:3', '1:-3', '100:3', '100:-3', '10000:3', '10000:-3', + 'all']: + try: + do('f.parsesequence(%s)' % `seq`) + except Error, msg: + print "Error:", msg + stuff = os.popen("pick %s 2>/dev/null" % `seq`).read() + list = map(string.atoi, string.split(stuff)) + print list, "<-- pick" do('f.listmessages()') |