[Python-checkins] python/nondist/sandbox/mailbox libmailbox.tex, 1.8, 1.9 mailbox.py, 1.7, 1.8 test_mailbox.py, 1.6, 1.7

gregorykjohnson@users.sourceforge.net gregorykjohnson at users.sourceforge.net
Sun Aug 14 00:41:45 CEST 2005


Update of /cvsroot/python/python/nondist/sandbox/mailbox
In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv10815

Modified Files:
	libmailbox.tex mailbox.py test_mailbox.py 
Log Message:
* Regularize list_, get_, set_, add_, remove_, join_, and leave_ names:
    * Maildir and MH: keep list_folders(), change open_folder() to
      get_folder(), introduce add_folder, and keep remove_folder().
    * Babyl: change list_labels() to get_labels().
    * MaildirMessage, mboxMessage, and MMDFMessage: keep get_flags() and
      set_flags(), change add_flags() to add_flag(), and change
      remove_flags() to remove_flag().
    * MHMessage: change list_sequences() to get_sequences(), introduce
      set_sequences(), change join_sequence() to add_sequence(), and
      change leave_sequence() to remove_sequence()
    * BabylMessage: change list_labels() to get_labels(), introduce
      set_labels(), and keep add_label() and remove_label()
* At the suggestion of A.M. Kuchling:
    * Avoid os.mknod(), for MacOS compatibility.
    * Introduce create=True parameter for Mailbox constructors.
    * Prefer iteritems() to items() in Mailbox.update().
    * Use fcntl=None to avoid checking globals().
    * Use os.path.dirname() instead of os.path.split()[0].
    * Use "':' in x" instead of "x.index(':') != -1".
    * Use os.path.getatime() instead of os.stat().st_atime.
* Remove module-level open() function, which clutters the API. Its
  original motivation was to regularize Mailbox constructors while keep
  backward compatability, but all Mailbox classes have been renamed and
  regularized except Maildir, which is already extremely similar.
* Introduce subclasses of Error: NoSuchMailboxError, NotEmptyError,
  ExternalClashError, FormatError.


Index: libmailbox.tex
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/libmailbox.tex,v
retrieving revision 1.8
retrieving revision 1.9
diff -u -d -r1.8 -r1.9
--- libmailbox.tex	5 Aug 2005 16:34:45 -0000	1.8
+++ libmailbox.tex	13 Aug 2005 22:41:33 -0000	1.9
@@ -75,33 +75,7 @@
 
 \class{Mailbox} itself is intended to define an interface and to be inherited
 from by format-specific subclasses but is not intended to be instantiated.
-Instead, you may directly instantiate a subclass or use the module-level
-\function{open()} function to do so.
-
-\begin{funcdesc}{open}{path\optional{, format\optional{, factory}}}
-Instantiate and return an instance of the appropriate \class{Mailbox} subclass
-for the mailbox at \var{path}. The mailbox is created if it does not already
-exist.
-    
-If \var{format} is specified, it should be one of "Maildir", "mbox", "MH",
-"Babyl", or "MMDF" (case insensitive). If \var{format} is not specified, then
-the format of the mailbox is automatically detected. Automatic detection
-involves inspecting the mailbox at \var{path} if such a mailbox exists or if
-no such mailbox exists inspecting \var{path} itself and assuming Maildir
-format if \var{path} ends with the system's path separator (e.g., "/" or
-"\textbackslash") or mbox format otherwise.
-
-Parameter \var{factory} is a callable object that accepts a file-like object
-containing a raw message as its parameter and returns a message
-representation. If \var{factory} is not specified, \class{Message} instances
-are used to represent messages.
-
-For historical reasons, some subclasses of \class{Mailbox} take instantiation
-arguments with different purposes, names, or default values. The
-\function{open()} function is intended to present a convenient, uniform
-interface for \class{Mailbox} instantiation while maintaining backward
-compatibility.
-\end{funcdesc}
+Instead, directly instantiate a subclass.
 
 \class{Mailbox} instances have the following methods:
 
@@ -256,11 +230,17 @@
 \subsubsection{\class{Maildir}}
 \label{mailbox-maildir}
 
-\begin{classdesc}{Maildir}{dirname\optional{, factory}}
+\begin{classdesc}{Maildir}{dirname\optional{, factory=rfc822.Message\optional{,
+create=True}}}
 A subclass of \class{Mailbox} for mailboxes in Maildir format. Parameter
-\var{dirname} is the path to the mailbox. Parameter \var{factory} has the same
-meaning as with the module-level \method{open()} function. For historical
-reasons, \var{factory} defaults to \class{rfc822.Message}.
+\var{factory} is a callable object that accepts a file-like object containing a
+raw message as its parameter and returns a message representation. If
+\var{factory} is \code{None}, \class{MaildirMessage} instances are used.
+If \var{create} is \code{True}, the mailbox is created if it does not exist.
+
+It is for historical reasons that \var{factory} defaults to
+\class{rfc822.Message} and that \var{dirname} is named as such rather than
+\var{path}.
 \end{classdesc}
 
 Maildir is a directory-based mailbox format invented for the qmail MTA and now
@@ -270,28 +250,35 @@
 without data corruption, so file locking is unnecessary.
 
 Folders, as introduced by the Courier MTA, are supported. Each folder is
-itself a Maildir mailbox and is represented as a \class{Maildir} instance. Any
-subdirectory of the main Maildir directory is considered a folder if
-\character{.} is the first character in its name. Folder names are represented
-without the leading dot. For example, "Sent.2005.07" would be the name of a
-folder implemented with a directory called ".Sent.2005.07" on the filesystem.
+itself a Maildir mailbox. Any subdirectory of the main Maildir directory is
+considered a folder if \character{.} is the first character in its name. Folder
+names are represented without the leading dot. For example, "Sent" would be the
+name of a folder implemented with a directory called ".Sent" on the filesystem.
+Folders should not be nested, i.e., a Maildir mailbox that is itself a folder
+should not contain other folders. Instead, logical nesting may be indicated
+using \character{.} to delimit levels---for example, "Archived.2005.07".
 
 \class{Maildir} instances have all of the methods of \class{Mailbox} in
 addition to the following:
 
 \begin{methoddesc}{list_folders}{}
-Return a list of the names of all folders. If there are no folders, the empty
-list is returned.
+Return a list of the names of all folders.
 \end{methoddesc}
 
-\begin{methoddesc}{open_folder}{name}
+\begin{methoddesc}{get_folder}{folder}
 Return a \class{Maildir} instance representing the folder whose name is
-\var{name}. The folder will be created if it does not exist.
+\var{folder}. A \exception{NoSuchMailboxError} exception is raised if the
+folder does not exist.
 \end{methoddesc}
 
-\begin{methoddesc}{remove_folder}{name}
-Delete the folder whose name is \var{name}. If the folder contains any
-messages, a \exception{mailbox.Error} exception will be raised and the folder
+\begin{methoddesc}{add_folder}{folder}
+Create a folder whose name is \var{folder} and return a \class{Maildir}
+instance representing it.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_folder}{folder}
+Delete the folder whose name is \var{folder}. If the folder contains any
+messages, a \exception{NotEmptyError} exception will be raised and the folder
 will not be deleted.
 \end{methoddesc}
 
@@ -301,13 +288,6 @@
 should do this occassionally.
 \end{methoddesc}
 
-\warning{Three \class{Maildir} methods---\method{add()},
-\method{__setitem__()}, and \method{update()}---generate unique file names
-based upon the current process ID. When using multiple threads, undetected
-clashes may occur and cause corruption of the mailbox unless threads are
-coordinated to avoid using these methods to manipulate the same mailbox
-simultaneously.}
-
 Some \class{Mailbox} methods implemented by \class{Maildir} deserve special
 remarks:
 
@@ -350,10 +330,12 @@
 \subsubsection{\class{mbox}}
 \label{mailbox-mbox}
 
-\begin{classdesc}{mbox}{path\optional{, factory}}
-A subclass of \class{Mailbox} for mailboxes in mbox format. Parameters
-\var{path} and \var{factory} has the same meaning as with the module-level
-\method{open()} function.
+\begin{classdesc}{mbox}{path\optional{, factory=None\optional{, create=True}}}
+A subclass of \class{Mailbox} for mailboxes in mbox format. Parameter
+\var{factory} is a callable object that accepts a file-like object containing a
+raw message as its parameter and returns a message representation. If
+\var{factory} is \code{None}, \class{mboxMessage} instances are used. If
+\var{create} is \code{True}, the mailbox is created if it does not exist.
 \end{classdesc}
 
 The mbox format is the classic format for storing mail on \UNIX{} systems. All
@@ -392,10 +374,12 @@
 \subsubsection{\class{MH}}
 \label{mailbox-mh}
 
-\begin{classdesc}{MH}{path\optional{, factory}}
-A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path}
-and \var{factory} has the same meaning as with the module-level \method{open()}
-function.
+\begin{classdesc}{MH}{path\optional{, factory=None\optional{, create=True}}}
+A subclass of \class{Mailbox} for mailboxes in MH format. Parameter
+\var{factory} is a callable object that accepts a file-like object containing a
+raw message as its parameter and returns a message representation. If
+\var{factory} is \code{None}, \class{MHMessage} instances are used. If
+\var{create} is \code{True}, the mailbox is created if it does not exist.
 \end{classdesc}
 
 MH is a directory-based mailbox format invented for the MH Message Handling
@@ -420,18 +404,23 @@
 the following:
 
 \begin{methoddesc}{list_folders}{}
-Return a list of the names of all folders. If there are no folders, the empty
-list is returned.
+Return a list of the names of all folders.
 \end{methoddesc}
 
-\begin{methoddesc}{open_folder}{name}
-Return an \class{MH} instance representing the folder whose name is \var{name}.
-The folder will be created if it does not exist.
+\begin{methoddesc}{get_folder}{folder}
+Return an \class{MH} instance representing the folder whose name is
+\var{folder}. A \exception{NoSuchMailboxError} exception is raised if the
+folder does not exist.
 \end{methoddesc}
 
-\begin{methoddesc}{remove_folder}{name}
-Delete the folder whose name is \var{name}. If the folder contains any
-messages, a \exception{mailbox.Error} exception will be raised and the folder
+\begin{methoddesc}{add_folder}{folder}
+Create a folder whose name is \var{folder} and return an \class{MH} instance
+representing it.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_folder}{folder}
+Delete the folder whose name is \var{folder}. If the folder contains any
+messages, a \exception{NotEmptyError} exception will be raised and the folder
 will not be deleted.
 \end{methoddesc}
 
@@ -474,12 +463,6 @@
 \class{MH} instances do not keep any open files, so this method does nothing.
 \end{methoddesc}
 
-\begin{classdesc}{MH}{path\optional{, factory}}
-A subclass of \class{Mailbox} for mailboxes in MH format. Parameters \var{path}
-and \var{factory} have the same meaning as with the module-level
-\method{open()} function.
-\end{classdesc}
-
 \class{MH} instances have all of the methods of \class{Mailbox} in addition to
 the following:
 
@@ -493,17 +476,19 @@
 \seelink{http://www.nongnu.org/nmh/}{nmh - Message Handling System}{Home page
 of \program{nmh}, a modern version of the original \program{mh}.}
 \seelink{http://www.ics.uci.edu/\tilde{}mh/book/}{MH \& nmh: Email for Users \&
-Programmers}{An open-source book on \program{mh} and \program{nmh}, with some
+Programmers}{A GPL-licensed book on \program{mh} and \program{nmh}, with some
 information on the mailbox format.}
 \end{seealso}
 
 \subsubsection{\class{Babyl}}
 \label{mailbox-babyl}
 
-\begin{classdesc}{Babyl}{path\optional{, factory}}
-A subclass of \class{Mailbox} for mailboxes in Babyl format. Parameters
-\var{path} and \var{factory} have the same meaning as with the module-level
-\method{open()} function.
+\begin{classdesc}{Babyl}{path\optional{, factory=None\optional{, create=True}}}
+A subclass of \class{Mailbox} for mailboxes in Babyl format. Parameter
+\var{factory} is a callable object that accepts a file-like object containing a
+raw message as its parameter and returns a message representation. If
+\var{factory} is \code{None}, \class{BabylMessage} instances are used. If
+\var{create} is \code{True}, the mailbox is created if it does not exist.
 \end{classdesc}
 
 Babyl is a single-file mailbox format invented for the \program{Rmail} mail
@@ -522,8 +507,8 @@
 \class{Babyl} instances have all of the methods of \class{Mailbox} in addition
 to the following:
 
-\begin{methoddesc}{list_labels}{}
-Return a list of all user-defined labels in the mailbox.
+\begin{methoddesc}{get_labels}{}
+Return a list of the names of all user-defined labels used in the mailbox.
 \end{methoddesc}
 
 Some \class{Mailbox} methods implemented by \class{Babyl} deserve special
@@ -546,10 +531,12 @@
 \subsubsection{\class{MMDF}}
 \label{mailbox-mmdf}
 
-\begin{classdesc}{MMDF}{path\optional{, factory}}
-A subclass of \class{Mailbox} for mailboxes in MMDF format. Parameters
-\var{path} and \var{factory} have the same meaning as with the module-level
-\method{open()} function.
+\begin{classdesc}{MMDF}{path\optional{, factory=None\optional{, create=True}}}
+A subclass of \class{Mailbox} for mailboxes in MMDF format. Parameter
+\var{factory} is a callable object that accepts a file-like object containing a
+raw message as its parameter and returns a message representation. If
+\var{factory} is \code{None}, \class{MMDFMessage} instances are used. If
+\var{create} is \code{True}, the mailbox is created if it does not exist.
 \end{classdesc}
 
 MMDF is a single-file mailbox format invented for the Multichannel Memorandum
@@ -671,30 +658,22 @@
 \end{methoddesc}
 
 \begin{methoddesc}{set_flags}{flags}
-Set the flags specified by \var{flags} and unset all others. Parameter
-\var{flags} should be the concatenation in any order of zero or more
-occurrences of each of \character{D}, \character{F}, \character{P},
-\character{R}, \character{S}, and \character{T}. The current "info" is
-overwritten whether or not it contains experimental information instead of
-flags.
+Set the flags specified by \var{flags} and unset all others.
 \end{methoddesc}
 
-\begin{methoddesc}{add_flags}{flags}
-Set the flags specified by \var{flags} (if they are not set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{D}, \character{F},
-\character{P}, \character{R}, \character{S}, and \character{T}. The current
-"info" is overwritten whether or not it contains experimental information
-instead of flags.
+\begin{methoddesc}{add_flag}{flag}
+Set the flag(s) specified by \var{flag} without changing other flags. To add
+more than one flag at a time, \var{flag} may be a string of more than one
+character. The current "info" is overwritten whether or not it contains
+experimental information rather than
+flags.
 \end{methoddesc}
 
-\begin{methoddesc}{remove_flags}{flags}
-Unset the flags specified by \var{flags} (if they are set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{D}, \character{F},
-\character{P}, \character{R}, \character{S}, and \character{T}. If "info"
-contains experimental information rather than flags, the current "info" is not
-modified.
+\begin{methoddesc}{remove_flag}{flag}
+Unset the flag(s) specified by \var{flag} without changing other flags. To
+remove more than one flag at a time, \var{flag} maybe a string of more than one
+character. If "info" contains experimental information rather than flags, the
+current "info" is not modified.
 \end{methoddesc}
 
 \begin{methoddesc}{get_info}{}
@@ -804,18 +783,16 @@
 \character{F}, and \character{A}.
 \end{methoddesc}
 
-\begin{methoddesc}{add_flags}{flags}
-Set the flags specified by \var{flags} (if they are not set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{R}, \character{O},
-\character{D}, \character{F}, and \character{A}.
+\begin{methoddesc}{add_flag}{flag}
+Set the flag(s) specified by \var{flag} without changing other flags. To add
+more than one flag at a time, \var{flag} may be a string of more than one
+character.
 \end{methoddesc}
 
-\begin{methoddesc}{remove_flags}{flags}
-Unset the flags specified by \var{flags} (if they are set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{R}, \character{O},
-\character{D}, \character{F}, and \character{A}.
+\begin{methoddesc}{remove_flag}{flag}
+Unset the flag(s) specified by \var{flag} without changing other flags. To
+remove more than one flag at a time, \var{flag} maybe a string of more than one
+character.
 \end{methoddesc}
 
 When an \class{mboxMessage} instance is created based upon a
@@ -888,16 +865,20 @@
 
 \class{MHMessage} instances offer the following methods:
 
-\begin{methoddesc}{list_sequences}{}
-Return a list of the names of sequences that include the message.
+\begin{methoddesc}{get_sequences}{}
+Return a list of the names of sequences that include this message.
 \end{methoddesc}
 
-\begin{methoddesc}{join_sequence}{sequence}
-Add \var{sequence} to the list of sequences that include the message.
+\begin{methoddesc}{set_sequences}{sequences}
+Set the list of sequences that include this message.
 \end{methoddesc}
 
-\begin{methoddesc}{leave_sequence}{sequence}
-Remove \var{sequence} from the list of sequences that include the message.
+\begin{methoddesc}{add_sequence}{sequence}
+Add \var{sequence} to the list of sequences that include this message.
+\end{methoddesc}
+
+\begin{methoddesc}{remove_sequence}{sequence}
+Remove \var{sequence} from the list of sequences that include this message.
 \end{methoddesc}
 
 When an \class{MHMessage} instance is created based upon a
@@ -963,10 +944,14 @@
 
 \class{BabylMessage} instances offer the following methods:
 
-\begin{methoddesc}{list_labels}{}
+\begin{methoddesc}{get_labels}{}
 Return a list of labels on the message.
 \end{methoddesc}
 
+\begin{methoddesc}{set_labels}{labels}
+Set the list of labels on the message to \var{labels}.
+\end{methoddesc}
+
 \begin{methoddesc}{add_label}{label}
 Add \var{label} to the list of labels on the message.
 \end{methoddesc}
@@ -1088,18 +1073,16 @@
 \character{F}, and \character{A}.
 \end{methoddesc}
 
-\begin{methoddesc}{add_flags}{flags}
-Set the flags specified by \var{flags} (if they are not set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{R}, \character{O},
-\character{D}, \character{F}, and \character{A}.
+\begin{methoddesc}{add_flag}{flag}
+Set the flag(s) specified by \var{flag} without changing other flags. To add
+more than one flag at a time, \var{flag} may be a string of more than one
+character.
 \end{methoddesc}
 
-\begin{methoddesc}{remove_flags}{flags}
-Unset the flags specified by \var{flags} (if they are set), and don't change
-other flags. Parameter \var{flags} should be the concatenation in any order of
-zero or more occurrences of each of \character{R}, \character{O},
-\character{D}, \character{F}, and \character{A}.
+\begin{methoddesc}{remove_flag}{flag}
+Unset the flag(s) specified by \var{flag} without changing other flags. To
+remove more than one flag at a time, \var{flag} maybe a string of more than one
+character.
 \end{methoddesc}
 
 When an \class{MMDFMessage} instance is created based upon a

Index: mailbox.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/mailbox.py,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- mailbox.py	5 Aug 2005 16:34:45 -0000	1.7
+++ mailbox.py	13 Aug 2005 22:41:33 -0000	1.8
@@ -16,21 +16,17 @@
 try:
     import fnctl
 except ImportError:
-    pass
+    fcntl = None
 
-__all__ = [ 'open', 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF',
+__all__ = [ 'Mailbox', 'Maildir', 'mbox', 'MH', 'Babyl', 'MMDF',
             'Message', 'MaildirMessage', 'mboxMessage', 'MHMessage',
             'BabylMessage', 'MMDFMessage' ]
 
 
-def open(path, format=None, factory=None):
-    """Open a mailbox at the given path and return a Mailbox instance.""" 
-
-
 class Mailbox:
     """A group of messages in a particular place."""
 
-    def __init__(self, path, factory=None):
+    def __init__(self, path, factory=None, create=True):
         """Initialize a Mailbox instance."""
         self._path = os.path.abspath(path)
         self._factory = factory
@@ -154,7 +150,9 @@
 
     def update(self, arg=None):
         """Change the messages that correspond to certain keys."""
-        if hasattr(arg, 'items'):
+        if hasattr(arg, 'iteritems'):
+            source = arg.iteritems()
+        elif hasattr(arg, 'items'):
             source = arg.items()
         else:
             source = arg
@@ -195,14 +193,17 @@
 class Maildir(Mailbox):
     """A qmail-style Maildir mailbox."""
 
-    def __init__(self, dirname, factory=rfc822.Message):
+    def __init__(self, dirname, factory=rfc822.Message, create=True):
         """Initialize a Maildir instance."""
-        Mailbox.__init__(self, dirname, factory)
+        Mailbox.__init__(self, dirname, factory, create)
         if not os.path.exists(self._path):
-            os.mkdir(self._path, 0700)
-            os.mkdir(os.path.join(self._path, 'tmp'), 0700)
-            os.mkdir(os.path.join(self._path, 'new'), 0700)
-            os.mkdir(os.path.join(self._path, 'cur'), 0700)
+            if create:
+                os.mkdir(self._path, 0700)
+                os.mkdir(os.path.join(self._path, 'tmp'), 0700)
+                os.mkdir(os.path.join(self._path, 'new'), 0700)
+                os.mkdir(os.path.join(self._path, 'cur'), 0700)
+            else:
+                raise NoSuchMailboxError, self._path
         self._toc = {}
 
     def add(self, message):
@@ -253,8 +254,8 @@
         else:
             # temp's subdir and suffix were defaults from add().
             dominant_subpath = old_subpath
-        subdir = os.path.split(dominant_subpath)[0]
-        if dominant_subpath.find(':') != -1:
+        subdir = os.path.dirname(dominant_subpath)
+        if ':' in dominant_subpath:
             suffix = ':' + dominant_subpath.split(':')[-1]
         else:
             suffix = ''
@@ -273,7 +274,7 @@
             f.close()
         subdir, name = os.path.split(subpath)
         msg.set_subdir(subdir)
-        if name.find(':') != -1:
+        if ':' in name:
             msg.set_info(name.split(':')[-1])
         return msg
 
@@ -327,27 +328,31 @@
                 result.append(entry[1:])
         return result
 
-    def open_folder(self, name):
-        """Return a Maildir for the named folder, creating it if necessary."""
-        path = os.path.join(self._path, '.' + name)
-        maildirfolder_path = os.path.join(path, 'maildirfolder')
+    def get_folder(self, folder):
+        """Return a Maildir instance for the named folder."""
+        return Maildir(os.path.join(self._path, '.' + folder), create=False)
+
+    def add_folder(self, folder):
+        """Create a folder and return a Maildir instance representing it."""
+        path = os.path.join(self._path, '.' + folder)
         result = Maildir(path)
+        maildirfolder_path = os.path.join(path, 'maildirfolder')
         if not os.path.exists(maildirfolder_path):
-            os.mknod(maildirfolder_path, 0600 | stat.S_IFREG)
+            os.close(os.open(maildirfolder_path, os.O_CREAT | os.O_WRONLY))
         return result
 
-    def remove_folder(self, name):
+    def remove_folder(self, folder):
         """Delete the named folder, which must be empty."""
-        path = os.path.join(self._path, '.' + name)
+        path = os.path.join(self._path, '.' + folder)
         for entry in os.listdir(os.path.join(path, 'new')) + \
                      os.listdir(os.path.join(path, 'cur')):
             if len(entry) < 1 or entry[0] != '.':
-                raise Error, "Folder '%s' contains message" % name
+                raise NotEmptyError, "Folder '%s' contains message" % folder
         for entry in os.listdir(path):
             if entry != 'new' and entry != 'cur' and entry != 'tmp' and \
                os.path.isdir(os.path.join(path, entry)):
-                raise Error, "Folder '%s' contains subdirectory '%s'" % \
-                              (name, entry)
+                raise NotEmptyError, "Folder '%s' contains subdirectory '%s'" \
+                              % (folder, entry)
         for root, dirs, files in os.walk(path, topdown=False):
             for entry in files:
                 os.remove(os.path.join(root, entry))
@@ -360,7 +365,7 @@
         now = time.time()
         for entry in os.listdir(os.path.join(self._path, 'tmp')):
             path = os.path.join(self._path, 'tmp', entry)
-            if now - os.stat(path).st_atime > 129600:   # 60 * 60 * 36
+            if now - os.path.getatime(path) > 129600:   # 60 * 60 * 36
                 os.remove(path)
 
     _count = 1  # This is used to generate unique file names.
@@ -385,7 +390,8 @@
             else:
                 raise
         else:
-            raise Error, "Name clash prevented file creation: '%s'" % path
+            raise ExternalClashError, \
+                  "Name clash prevented file creation: '%s'" % path
 
     def _refresh(self):
         """Update table of contents mapping."""
@@ -412,14 +418,17 @@
 class _singlefileMailbox(Mailbox):
     """A single-file mailbox."""
 
-    def __init__(self, path, factory=None):
+    def __init__(self, path, factory=None, create=True):
         """Initialize a single-file mailbox."""
-        Mailbox.__init__(self, path, factory)
+        Mailbox.__init__(self, path, factory, create)
         try:
             f = file(self._path, 'r+')
         except IOError, e:
             if e.errno == errno.ENOENT:
-                f = file(self._path, 'w+')
+                if create:
+                    f = file(self._path, 'w+')
+                else:
+                    raise NoSuchMailboxError, self._path
             elif e.errno == errno.EACCES:
                 f = file(self._path, 'r')
             else:
@@ -544,7 +553,8 @@
     def _assert_mtime(self):
         """Raise an exception if the file has been externally modified."""
         if self._mtime != os.fstat(self._file.fileno()).st_mtime:
-            raise Error, 'External modifications detected: use refresh()'
+            raise ExternalClashError, \
+                  'External modifications detected: use refresh()'
 
     def _set_mtime(self):
         """Store the current mtime."""
@@ -625,10 +635,10 @@
 class mbox(_mboxMMDF):
     """A classic mbox mailbox."""
 
-    def __init__(self, path, factory=None):
+    def __init__(self, path, factory=None, create=True):
         """Initialize an mbox mailbox."""
         self._message_factory = mboxMessage
-        _mboxMMDF.__init__(self, path, factory)
+        _mboxMMDF.__init__(self, path, factory, create)
 
     def _pre_message_hook(self, f):
         """Called before writing each message to file f."""
@@ -657,10 +667,10 @@
 class MMDF(_mboxMMDF):
     """An MMDF mailbox."""
 
-    def __init__(self, path, factory=None):
+    def __init__(self, path, factory=None, create=True):
         """Initialize an MMDF mailbox."""
         self._message_factory = MMDFMessage
-        _mboxMMDF.__init__(self, path, factory)
+        _mboxMMDF.__init__(self, path, factory, create)
 
     def _pre_message_hook(self, f):
         """Called before writing each message to file f."""
@@ -701,13 +711,16 @@
 class MH(Mailbox):
     """An MH mailbox."""
 
-    def __init__(self, path, factory=None):
+    def __init__(self, path, factory=None, create=True):
         """Initialize an MH instance."""
-        Mailbox.__init__(self, path, factory)
+        Mailbox.__init__(self, path, factory, create)
         if not os.path.exists(self._path):
-            os.mkdir(self._path, 0700)
-            os.mknod(os.path.join(self._path, '.mh_sequences'),
-                     0600 | stat.S_IFREG)
+            if create:
+                os.mkdir(self._path, 0700)
+                os.close(os.open(os.path.join(self._path, '.mh_sequences'),
+                                 os.O_CREAT | os.O_WRONLY, 0600))
+            else:
+                raise NoSuchMailboxError, self._path
 
     def add(self, message):
         """Add message and return assigned key."""
@@ -779,7 +792,7 @@
             f.close()
         for name, key_list in self.get_sequences():
             if key in key_list:
-                msg.join_sequence(name)
+                msg.add_sequence(name)
         return msg
 
     def get_string(self, key):
@@ -829,27 +842,32 @@
         return
 
     def list_folders(self):
-        """Return a list of folders in this mailbox."""
+        """Return a list of folder names."""
         result = []
         for entry in os.listdir(self._path):
             if os.path.isdir(os.path.join(self._path, entry)):
                 result.append(entry)
         return result
 
-    def open_folder(self, name):
-        """Return an MH instance for folder name, creating it if necessary."""
-        return MH(os.path.join(self._path, name))
+    def get_folder(self, folder):
+        """Return an MH instance for the named folder."""
+        return MH(os.path.join(self._path, folder), create=False)
 
-    def remove_folder(self, name):
-        """Delete folder name."""
-        path = os.path.join(self._path, name)
+    def add_folder(self, folder):
+        """Create a folder and return an MH instance representing it."""
+        return Maildir(os.path.join(self._path, '.' + folder))
+
+    def remove_folder(self, folder):
+        """Delete the named folder, which must be empty."""
+        path = os.path.join(self._path, folder)
         entries = os.listdir(path)
         if entries == ['.mh_sequences']:
             os.remove(os.path.join(path, '.mh_sequences'))
         elif entries == []:
             pass
         else:
-            raise Error, "Folder '%s' is not empty" % self._path
+            raise NotEmptyError, "Folder '%s' is not empty" % \
+                                 self._path
         os.rmdir(path)
 
     def get_sequences(self):
@@ -871,8 +889,8 @@
                     results[name] = [key for key in sorted(keys) \
                                          if key in all_keys]
                 except ValueError:
-                    raise Error, "Invalid sequence specification: '%s'" % \
-                                 line.rstrip()
+                    raise FormatError, "Invalid sequence specification: " % \
+                                       "'%s'" % line.rstrip()
         finally:
             f.close()
         return results
@@ -942,7 +960,7 @@
 
     def _dump_sequences(self, message, key):
         """Inspect a new MHMessage and update sequences appropriately."""
-        pending_sequences = message.list_sequences()
+        pending_sequences = message.get_sequences()
         all_sequences = self.get_sequences()
         for name, key_list in all_sequences.iteritems():
             if name in pending_sequences:
@@ -1004,7 +1022,7 @@
         """Return a file-like representation or raise a KeyError."""
         return StringIO.StringIO(self.get_string(key))
 
-    def list_labels(self):
+    def get_labels(self):
         """Return a list of user-defined labels in the mailbox."""
         raise NotImplementedError, 'Method not yet implemented'
 
@@ -1172,14 +1190,14 @@
         """Set the given flags and unset all others."""
         self._info = '2,' + ''.join(sorted(flags))
 
-    def add_flags(self, flags):
-        """Set the given flags without changing others."""
-        self.set_flags(''.join(set(self.get_flags()) | set(flags)))
+    def add_flag(self, flag):
+        """Set the given flag(s) without changing others."""
+        self.set_flags(''.join(set(self.get_flags()) | set(flag)))
 
-    def remove_flags(self, flags):
-        """Unset the given string flags (if set) without changing others."""
+    def remove_flag(self, flag):
+        """Unset the given string flag(s) without changing others."""
         if self.get_flags() != '':
-            self.set_flags(''.join(set(self.get_flags()) - set(flags)))
+            self.set_flags(''.join(set(self.get_flags()) - set(flag)))
 
     def get_info(self):
         """Get the message's "info" as a string."""
@@ -1200,23 +1218,23 @@
         elif isinstance(message, _mboxMMDFMessage):
             flags = set(self.get_flags())
             if 'S' in flags:
-                message.add_flags('R')
+                message.add_flag('R')
             if self.get_subdir() == 'cur':
-                message.add_flags('O')
+                message.add_flag('O')
             if 'T' in flags:
-                message.add_flags('D')
+                message.add_flag('D')
             if 'F' in flags:
-                message.add_flags('F')
+                message.add_flag('F')
             if 'R' in flags:
-                message.add_flags('A')
+                message.add_flag('A')
         elif isinstance(message, MHMessage):
             flags = set(self.get_flags())
             if 'S' not in flags:
-                message.join_sequence('unseen')
+                message.add_sequence('unseen')
             if 'R' in flags:
-                message.join_sequence('replied')
+                message.add_sequence('replied')
             if 'F' in flags:
-                message.join_sequence('flagged')
+                message.add_sequence('flagged')
         elif isinstance(message, BabylMessage):
             flags = set(self.get_flags())
             if 'S' not in flags:
@@ -1287,14 +1305,14 @@
         except KeyError:
             self.add_header('X-Status', xstatus_flags)
 
-    def add_flags(self, flags):
-        """Set the given flags without changing others."""
-        self.set_flags(''.join(set(self.get_flags()) | set(flags)))
+    def add_flag(self, flag):
+        """Set the given flag(s) without changing others."""
+        self.set_flags(''.join(set(self.get_flags()) | set(flag)))
 
-    def remove_flags(self, flags):
-        """Unset the given string flags (if set) without changing others."""
+    def remove_flag(self, flag):
+        """Unset the given string flag(s) without changing others."""
         if 'Status' in self or 'X-Status' in self:
-            self.set_flags(''.join(set(self.get_flags()) - set(flags)))
+            self.set_flags(''.join(set(self.get_flags()) - set(flag)))
 
     def _explain_to(self, message):
         """Copy mbox- or MMDF-specific state to message insofar as possible."""
@@ -1303,24 +1321,24 @@
             if 'O' in flags:
                 message.set_subdir('cur')
             if 'F' in flags:
-                message.add_flags('F')
+                message.add_flag('F')
             if 'A' in flags:
-                message.add_flags('R')
+                message.add_flag('R')
             if 'R' in flags:
-                message.add_flags('S')
+                message.add_flag('S')
             if 'D' in flags:
-                message.add_flags('T')
+                message.add_flag('T')
         elif isinstance(message, _mboxMMDFMessage):
             message.set_flags(self.get_flags())
             message.set_from(self.get_from())
         elif isinstance(message, MHMessage):
             flags = set(self.get_flags())
             if 'R' not in flags:
-                message.join_sequence('unseen')
+                message.add_sequence('unseen')
             if 'A' in flags:
-                message.join_sequence('replied')
+                message.add_sequence('replied')
             if 'F' in flags:
-                message.join_sequence('flagged')
+                message.add_sequence('flagged')
         elif isinstance(message, BabylMessage):
             flags = set(self.get_flags())
             if 'R' not in flags:
@@ -1347,11 +1365,15 @@
         self._sequences = []
         Message.__init__(self, message)
 
-    def list_sequences(self):
+    def get_sequences(self):
         """Return a list of sequences that include the message."""
         return self._sequences[:]
 
-    def join_sequence(self, sequence):
+    def set_sequences(self, sequences):
+        """Set the list of sequences that include the message."""
+        self._sequences = list(sequences)
+
+    def add_sequence(self, sequence):
         """Add sequence to list of sequences including the message."""
         if isinstance(sequence, str):
             if not sequence in self._sequences:
@@ -1359,7 +1381,7 @@
         else:
             raise TypeError, "sequence must be a string"
 
-    def leave_sequence(self, sequence):
+    def remove_sequence(self, sequence):
         """Remove sequence from the list of sequences including the message."""
         try:
             self._sequences.remove(sequence)
@@ -1369,31 +1391,31 @@
     def _explain_to(self, message):
         """Copy MH-specific state to message insofar as possible."""
         if isinstance(message, MaildirMessage):
-            sequences = set(self.list_sequences())
+            sequences = set(self.get_sequences())
             if 'unseen' in sequences:
                 message.set_subdir('cur')
             else:
                 message.set_subdir('cur')
-                message.add_flags('S')
+                message.add_flag('S')
             if 'flagged' in sequences:
-                message.add_flags('F')
+                message.add_flag('F')
             if 'replied' in sequences:
-                message.add_flags('R')
+                message.add_flag('R')
         elif isinstance(message, _mboxMMDFMessage):
-            sequences = set(self.list_sequences())
+            sequences = set(self.get_sequences())
             if 'unseen' not in sequences:
-                message.add_flags('RO')
+                message.add_flag('RO')
             else:
-                message.add_flags('O')
+                message.add_flag('O')
             if 'flagged' in sequences:
-                message.add_flags('F')
+                message.add_flag('F')
             if 'replied' in sequences:
-                message.add_flags('A')
+                message.add_flag('A')
         elif isinstance(message, MHMessage):
-            for sequence in self.list_sequences():
-                message.join_sequence(sequence)
+            for sequence in self.get_sequences():
+                message.add_sequence(sequence)
         elif isinstance(message, BabylMessage):
-            sequences = set(self.list_sequences())
+            sequences = set(self.get_sequences())
             if 'unseen' in sequences:
                 message.add_label('unseen')
             if 'replied' in sequences:
@@ -1413,10 +1435,14 @@
         self._visible = Message()
         Message.__init__(self, message)
 
-    def list_labels(self):
+    def get_labels(self):
         """Return a list of labels on the message."""
         return self._labels[:]
 
+    def set_labels(self, labels):
+        """Set the list of labels on the message."""
+        self._labels = list(labels)
+
     def add_label(self, label):
         """Add label to list of labels on the message."""
         if isinstance(label, str):
@@ -1454,37 +1480,37 @@
     def _explain_to(self, message):
         """Copy Babyl-specific state to message insofar as possible."""
         if isinstance(message, MaildirMessage):
-            labels = set(self.list_labels())
+            labels = set(self.get_labels())
             if 'unseen' in labels:
                 message.set_subdir('cur')
             else:
                 message.set_subdir('cur')
-                message.add_flags('S')
+                message.add_flag('S')
             if 'forwarded' in labels or 'resent' in labels:
-                message.add_flags('P')
+                message.add_flag('P')
             if 'answered' in labels:
-                message.add_flags('R')
+                message.add_flag('R')
             if 'deleted' in labels:
-                message.add_flags('T')
+                message.add_flag('T')
         elif isinstance(message, _mboxMMDFMessage):
-            labels = set(self.list_labels())
+            labels = set(self.get_labels())
             if 'unseen' not in labels:
-                message.add_flags('RO')
+                message.add_flag('RO')
             else:
-                message.add_flags('O')
+                message.add_flag('O')
             if 'deleted' in labels:
-                message.add_flags('D')
+                message.add_flag('D')
             if 'answered' in labels:
-                message.add_flags('A')
+                message.add_flag('A')
         elif isinstance(message, MHMessage):
-            labels = set(self.list_labels())
+            labels = set(self.get_labels())
             if 'unseen' in labels:
-                message.join_sequence('unseen')
+                message.add_sequence('unseen')
             if 'answered' in labels:
-                message.join_sequence('replied')
+                message.add_sequence('replied')
         elif isinstance(message, BabylMessage):
             message.set_visible(self.get_visible())
-            for label in self.list_labels():
+            for label in self.get_labels():
                 message.add_label(label)
         elif isinstance(message, Message):
             pass
@@ -1588,21 +1614,18 @@
         return _ProxyFile._read(self, size, read_method)
 
 
-class Error(Exception):
-    """Raised for module-specific errors."""
-
-
 def _lock_file(f, path, system=True, dot=True):
     """Lock file f using lockf, flock, and dot locking."""
     lockf_done = flock_done = dotlock_done = False
     try:
-        if system and 'fcntl' in globals():
+        if system and fcntl:
             try:
                 fcntl.lockf(f, fcntl.LOCK_EX | fcntl.LOCK_NB)
                 lockf_done = True
             except IOError, e:
                 if e.errno == errno.EAGAIN:
-                    raise Error, "lockf: lock unavailable: %s" % path
+                    raise ExternalClashError, \
+                          "lockf: lock unavailable: %s" % path
                 else:
                     raise
             try:
@@ -1610,7 +1633,8 @@
                 flock_done = True
             except IOError, e:
                 if e.errno == errno.EWOULDBLOCK:
-                    raise Error, "flock: lock unavailable: %s" % path
+                    raise ExternalClashError, \
+                          "flock: lock unavailable: %s" % path
                 else:
                     raise
         if dot:
@@ -1637,7 +1661,7 @@
                         os.remove(tmp)
                     except:
                         pass
-                    raise Error, 'dot lock unavailable: %s' % path
+                    raise ExternalClashError, 'dot lock unavailable: %s' % path
                 else:
                     raise
     except:
@@ -1651,7 +1675,7 @@
 
 def _unlock_file(f, path, system=True, dot=True):
     """Unlock file f using lockf, flock, and dot locking."""
-    if system and 'fcntl' in globals():
+    if system and fcntl:
         fcntl.lockf(f, fcntl.LOCK_UN)
         fcntl.flock(f, fcntl.LOCK_UN)
     if dot and os.path.exists(path + '.lock'):
@@ -1660,3 +1684,18 @@
 def _create_carefully(path):
     """Create a file if it doesn't exist and open for reading and writing."""
     return os.fdopen(os.open(path, os.O_CREAT | os.O_EXCL | os.O_RDWR), 'r+')
+
+class Error(Exception):
+    """Raised for module-specific errors."""
+
+class NoSuchMailboxError(Error):
+    """The specified mailbox does not exist and won't be created."""
+
+class NotEmptyError(Error):
+    """The specified mailbox is not empty and deletion was requested."""
+
+class ExternalClashError(Error):
+    """Another process caused an action to fail."""
+
+class FormatError(Error):
+    """A file appears to have an invalid format."""

Index: test_mailbox.py
===================================================================
RCS file: /cvsroot/python/python/nondist/sandbox/mailbox/test_mailbox.py,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- test_mailbox.py	5 Aug 2005 16:34:45 -0000	1.6
+++ test_mailbox.py	13 Aug 2005 22:41:33 -0000	1.7
@@ -487,32 +487,33 @@
 
     def test_list_folders(self):
         # List folders
-        self._box.open_folder('one')
-        self._box.open_folder('two')
-        self._box.open_folder('three')
+        self._box.add_folder('one')
+        self._box.add_folder('two')
+        self._box.add_folder('three')
         self.assert_(len(self._box.list_folders()) == 3)
         self.assert_(set(self._box.list_folders()) ==
                      set(('one', 'two', 'three')))
 
-    def test_open_folder(self):
+    def test_get_folder(self):
         # Open folders
-        folder0 = self._box.open_folder('foo.bar')
+        self._box.add_folder('foo.bar')
+        folder0 = self._box.get_folder('foo.bar')
         folder0.add(self._template % 'bar')
         self.assert_(os.path.isdir(os.path.join(self._path, '.foo.bar')))
-        folder1 = self._box.open_folder('foo.bar')
+        folder1 = self._box.get_folder('foo.bar')
         self.assert_(folder1.get_string(folder1.keys()[0]) == \
                      self._template % 'bar')
 
-    def test_remove_folder(self):
+    def test_add_and_remove_folders(self):
         # Delete folders
-        self._box.open_folder('one')
-        self._box.open_folder('two')
+        self._box.add_folder('one')
+        self._box.add_folder('two')
         self.assert_(len(self._box.list_folders()) == 2)
         self.assert_(set(self._box.list_folders()) == set(('one', 'two')))
         self._box.remove_folder('one')
         self.assert_(len(self._box.list_folders()) == 1)
         self.assert_(set(self._box.list_folders()) == set(('two',)))
-        self._box.open_folder('three')
+        self._box.add_folder('three')
         self.assert_(len(self._box.list_folders()) == 2)
         self.assert_(set(self._box.list_folders()) == set(('two', 'three')))
         self._box.remove_folder('three')
@@ -775,7 +776,7 @@
         self._check_sample(msg)
 
     def test_flags(self):
-        # Use get_flags(), set_flags(), add_flags(), remove_flags()
+        # Use get_flags(), set_flags(), add_flag(), remove_flag()
         msg = mailbox.MaildirMessage(_sample_message)
         self.assert_(msg.get_flags() == '')
         self.assert_(msg.get_subdir() == 'new')
@@ -784,9 +785,9 @@
         self.assert_(msg.get_flags() == 'F')
         msg.set_flags('SDTP')
         self.assert_(msg.get_flags() == 'DPST')
-        msg.add_flags('FT')
+        msg.add_flag('FT')
         self.assert_(msg.get_flags() == 'DFPST')
-        msg.remove_flags('TDRP')
+        msg.remove_flag('TDRP')
         self.assert_(msg.get_flags() == 'FS')
         self.assert_(msg.get_subdir() == 'new')
         self._check_sample(msg)
@@ -810,10 +811,10 @@
         msg.set_info('1,')
         self.assert_(msg.get_flags() == '')
         self.assert_(msg.get_info() == '1,')
-        msg.remove_flags('RPT')
+        msg.remove_flag('RPT')
         self.assert_(msg.get_flags() == '')
         self.assert_(msg.get_info() == '1,')
-        msg.add_flags('D')
+        msg.add_flag('D')
         self.assert_(msg.get_flags() == 'D')
         self.assert_(msg.get_info() == '2,D')
         self._check_sample(msg)
@@ -845,16 +846,16 @@
         self._check_from(msg, 'blah at temp')
 
     def test_flags(self):
-        # Use get_flags(), set_flags(), add_flags(), remove_flags()
+        # Use get_flags(), set_flags(), add_flag(), remove_flag()
         msg = mailbox.mboxMessage(_sample_message)
         self.assert_(msg.get_flags() == '')
         msg.set_flags('F')
         self.assert_(msg.get_flags() == 'F')
         msg.set_flags('XODR')
         self.assert_(msg.get_flags() == 'RODX')
-        msg.add_flags('FA')
+        msg.add_flag('FA')
         self.assert_(msg.get_flags() == 'RODFAX')
-        msg.remove_flags('FDXA')
+        msg.remove_flag('FDXA')
         self.assert_(msg.get_flags() == 'RO')
         self._check_sample(msg)
 
@@ -879,21 +880,27 @@
         self.assert_(msg._sequences == [])
 
     def test_sequences(self):
-        # List, join, and leave sequences
+        # Get, set, join, and leave sequences
         msg = mailbox.MHMessage(_sample_message)
-        self.assert_(msg.list_sequences() == [])
-        msg.join_sequence('unseen')
-        self.assert_(msg.list_sequences() == ['unseen'])
-        msg.join_sequence('flagged')
-        self.assert_(msg.list_sequences() == ['unseen', 'flagged'])
-        msg.join_sequence('flagged')
-        self.assert_(msg.list_sequences() == ['unseen', 'flagged'])
-        msg.leave_sequence('unseen')
-        self.assert_(msg.list_sequences() == ['flagged'])
-        msg.join_sequence('foobar')
-        self.assert_(msg.list_sequences() == ['flagged', 'foobar'])
-        msg.leave_sequence('replied')
-        self.assert_(msg.list_sequences() == ['flagged', 'foobar'])
+        self.assert_(msg.get_sequences() == [])
+        msg.set_sequences(['foobar'])
+        self.assert_(msg.get_sequences() == ['foobar'])
+        msg.set_sequences([])
+        self.assert_(msg.get_sequences() == [])
+        msg.add_sequence('unseen')
+        self.assert_(msg.get_sequences() == ['unseen'])
+        msg.add_sequence('flagged')
+        self.assert_(msg.get_sequences() == ['unseen', 'flagged'])
+        msg.add_sequence('flagged')
+        self.assert_(msg.get_sequences() == ['unseen', 'flagged'])
+        msg.remove_sequence('unseen')
+        self.assert_(msg.get_sequences() == ['flagged'])
+        msg.add_sequence('foobar')
+        self.assert_(msg.get_sequences() == ['flagged', 'foobar'])
+        msg.remove_sequence('replied')
+        self.assert_(msg.get_sequences() == ['flagged', 'foobar'])
+        msg.set_sequences(['foobar', 'replied'])
+        self.assert_(msg.get_sequences() == ['foobar', 'replied'])
 
 
 class TestBabylMessage(TestMessage):
@@ -904,21 +911,27 @@
         self.assert_(msg._labels == [])
 
     def test_labels(self):
-        # List, add, and remove labels
+        # Get, set, join, and leave labels
         msg = mailbox.BabylMessage(_sample_message)
-        self.assert_(msg.list_labels() == [])
+        self.assert_(msg.get_labels() == [])
+        msg.set_labels(['foobar'])
+        self.assert_(msg.get_labels() == ['foobar'])
+        msg.set_labels([])
+        self.assert_(msg.get_labels() == [])
         msg.add_label('filed')
-        self.assert_(msg.list_labels() == ['filed'])
+        self.assert_(msg.get_labels() == ['filed'])
         msg.add_label('resent')
-        self.assert_(msg.list_labels() == ['filed', 'resent'])
+        self.assert_(msg.get_labels() == ['filed', 'resent'])
         msg.add_label('resent')
-        self.assert_(msg.list_labels() == ['filed', 'resent'])
+        self.assert_(msg.get_labels() == ['filed', 'resent'])
         msg.remove_label('filed')
-        self.assert_(msg.list_labels() == ['resent'])
+        self.assert_(msg.get_labels() == ['resent'])
         msg.add_label('foobar')
-        self.assert_(msg.list_labels() == ['resent', 'foobar'])
+        self.assert_(msg.get_labels() == ['resent', 'foobar'])
         msg.remove_label('unseen')
-        self.assert_(msg.list_labels() == ['resent', 'foobar'])
+        self.assert_(msg.get_labels() == ['resent', 'foobar'])
+        msg.set_labels(['foobar', 'answered'])
+        self.assert_(msg.get_labels() == ['foobar', 'answered'])
 
     def test_visible(self):
         # Get, set, and update visible headers
@@ -1007,7 +1020,7 @@
                  ('T', ['unseen']), ('DFPRST', ['replied', 'flagged']))
         for setting, result in pairs:
             msg_maildir.set_flags(setting)
-            self.assert_(mailbox.MHMessage(msg_maildir).list_sequences() == \
+            self.assert_(mailbox.MHMessage(msg_maildir).get_sequences() == \
                          result)
 
     def test_maildir_to_babyl(self):
@@ -1019,7 +1032,7 @@
                  ('DFPRST', ['deleted', 'answered', 'forwarded']))
         for setting, result in pairs:
             msg_maildir.set_flags(setting)
-            self.assert_(mailbox.BabylMessage(msg_maildir).list_labels() == \
+            self.assert_(mailbox.BabylMessage(msg_maildir).get_labels() == \
                          result)
 
     def test_mboxmmdf_to_maildir(self):
@@ -1057,7 +1070,7 @@
                      ('RODFA', ['replied', 'flagged']))
             for setting, result in pairs:
                 msg_mboxMMDF.set_flags(setting)
-                self.assert_(mailbox.MHMessage(msg_mboxMMDF).list_sequences() \
+                self.assert_(mailbox.MHMessage(msg_mboxMMDF).get_sequences() \
                              == result)
 
     def test_mboxmmdf_to_babyl(self):
@@ -1070,20 +1083,20 @@
                      ('RODFA', ['deleted', 'answered']))
             for setting, result in pairs:
                 msg.set_flags(setting)
-                self.assert_(mailbox.BabylMessage(msg).list_labels() == result)
+                self.assert_(mailbox.BabylMessage(msg).get_labels() == result)
 
     def test_mh_to_maildir(self):
         # Convert MHMessage to MaildirMessage
         pairs = (('unseen', ''), ('replied', 'RS'), ('flagged', 'FS'))
         for setting, result in pairs:
             msg = mailbox.MHMessage(_sample_message)
-            msg.join_sequence(setting)
+            msg.add_sequence(setting)
             self.assert_(mailbox.MaildirMessage(msg).get_flags() == result)
             self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
         msg = mailbox.MHMessage(_sample_message)
-        msg.join_sequence('unseen')
-        msg.join_sequence('replied')
-        msg.join_sequence('flagged')
+        msg.add_sequence('unseen')
+        msg.add_sequence('replied')
+        msg.add_sequence('flagged')
         self.assert_(mailbox.MaildirMessage(msg).get_flags() == 'FR')
         self.assert_(mailbox.MaildirMessage(msg).get_subdir() == 'cur')
 
@@ -1092,23 +1105,23 @@
         pairs = (('unseen', 'O'), ('replied', 'ROA'), ('flagged', 'ROF'))
         for setting, result in pairs:
             msg = mailbox.MHMessage(_sample_message)
-            msg.join_sequence(setting)
+            msg.add_sequence(setting)
             for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
                 self.assert_(class_(msg).get_flags() == result)
         msg = mailbox.MHMessage(_sample_message)
-        msg.join_sequence('unseen')
-        msg.join_sequence('replied')
-        msg.join_sequence('flagged')
+        msg.add_sequence('unseen')
+        msg.add_sequence('replied')
+        msg.add_sequence('flagged')
         for class_ in (mailbox.mboxMessage, mailbox.MMDFMessage):
             self.assert_(class_(msg).get_flags() == 'OFA')
 
     def test_mh_to_mh(self):
         # Convert MHMessage to MHMessage
         msg = mailbox.MHMessage(_sample_message)
-        msg.join_sequence('unseen')
-        msg.join_sequence('replied')
-        msg.join_sequence('flagged')
-        self.assert_(mailbox.MHMessage(msg).list_sequences() == \
+        msg.add_sequence('unseen')
+        msg.add_sequence('replied')
+        msg.add_sequence('flagged')
+        self.assert_(mailbox.MHMessage(msg).get_sequences() == \
                      ['unseen', 'replied', 'flagged'])
 
     def test_mh_to_babyl(self):
@@ -1117,13 +1130,13 @@
                  ('flagged', []))
         for setting, result in pairs:
             msg = mailbox.MHMessage(_sample_message)
-            msg.join_sequence(setting)
-            self.assert_(mailbox.BabylMessage(msg).list_labels() == result)
+            msg.add_sequence(setting)
+            self.assert_(mailbox.BabylMessage(msg).get_labels() == result)
         msg = mailbox.MHMessage(_sample_message)
-        msg.join_sequence('unseen')
-        msg.join_sequence('replied')
-        msg.join_sequence('flagged')
-        self.assert_(mailbox.BabylMessage(msg).list_labels() == \
+        msg.add_sequence('unseen')
+        msg.add_sequence('replied')
+        msg.add_sequence('flagged')
+        self.assert_(mailbox.BabylMessage(msg).get_labels() == \
                      ['unseen', 'answered'])
 
     def test_babyl_to_maildir(self):
@@ -1168,12 +1181,12 @@
         for setting, result in pairs:
             msg = mailbox.BabylMessage(_sample_message)
             msg.add_label(setting)
-            self.assert_(mailbox.MHMessage(msg).list_sequences() == result)
+            self.assert_(mailbox.MHMessage(msg).get_sequences() == result)
         msg = mailbox.BabylMessage(_sample_message)
         for label in ('unseen', 'deleted', 'filed', 'answered', 'forwarded',
                       'edited', 'resent'):
             msg.add_label(label)
-        self.assert_(mailbox.MHMessage(msg).list_sequences() == \
+        self.assert_(mailbox.MHMessage(msg).get_sequences() == \
                      ['unseen', 'replied'])
 
     def test_babyl_to_babyl(self):
@@ -1184,9 +1197,9 @@
                       'edited', 'resent'):
             msg.add_label(label)       
         msg2 = mailbox.BabylMessage(msg)
-        self.assert_(msg2.list_labels() == ['unseen', 'deleted', 'filed',
-                                            'answered', 'forwarded', 'edited',
-                                            'resent'])
+        self.assert_(msg2.get_labels() == ['unseen', 'deleted', 'filed',
+                                           'answered', 'forwarded', 'edited',
+                                           'resent'])
         self.assert_(msg.get_visible().keys() == msg2.get_visible().keys())
         for key in msg.get_visible().keys():
             self.assert_(msg.get_visible()[key] == msg2.get_visible()[key])



More information about the Python-checkins mailing list