Merged revisions 76034,76054 via svnmerge from

svn+ssh://pythondev@svn.python.org/python/trunk

........
  r76034 | antoine.pitrou | 2009-11-01 22:29:33 +0100 (dim., 01 nov. 2009) | 3 lines

  This should finally fix #6896. Let's watch the buildbots.
........
  r76054 | antoine.pitrou | 2009-11-02 12:34:27 +0100 (lun., 02 nov. 2009) | 3 lines

  Since r76034 was successful, add a NEWS entry for it.
........
This commit is contained in:
Antoine Pitrou 2009-11-02 11:36:51 +00:00
parent 9166e6afdf
commit 03f13445c9
3 changed files with 19 additions and 1 deletions

View File

@ -234,6 +234,9 @@ class Maildir(Mailbox):
raise NoSuchMailboxError(self._path) raise NoSuchMailboxError(self._path)
self._toc = {} self._toc = {}
self._last_read = None # Records last time we read cur/new self._last_read = None # Records last time we read cur/new
# NOTE: we manually invalidate _last_read each time we do any
# modifications ourselves, otherwise we might get tripped up by
# bogus mtime behaviour on some systems (see issue #6896).
def add(self, message): def add(self, message):
"""Add message and return assigned key.""" """Add message and return assigned key."""
@ -267,11 +270,15 @@ class Maildir(Mailbox):
raise raise
if isinstance(message, MaildirMessage): if isinstance(message, MaildirMessage):
os.utime(dest, (os.path.getatime(dest), message.get_date())) os.utime(dest, (os.path.getatime(dest), message.get_date()))
# Invalidate cached toc
self._last_read = None
return uniq return uniq
def remove(self, key): def remove(self, key):
"""Remove the keyed message; raise KeyError if it doesn't exist.""" """Remove the keyed message; raise KeyError if it doesn't exist."""
os.remove(os.path.join(self._path, self._lookup(key))) os.remove(os.path.join(self._path, self._lookup(key)))
# Invalidate cached toc (only on success)
self._last_read = None
def discard(self, key): def discard(self, key):
"""If the keyed message exists, remove it.""" """If the keyed message exists, remove it."""
@ -306,6 +313,8 @@ class Maildir(Mailbox):
if isinstance(message, MaildirMessage): if isinstance(message, MaildirMessage):
os.utime(new_path, (os.path.getatime(new_path), os.utime(new_path, (os.path.getatime(new_path),
message.get_date())) message.get_date()))
# Invalidate cached toc
self._last_read = None
def get_message(self, key): def get_message(self, key):
"""Return a Message representation or raise a KeyError.""" """Return a Message representation or raise a KeyError."""
@ -360,7 +369,9 @@ class Maildir(Mailbox):
def flush(self): def flush(self):
"""Write any pending changes to disk.""" """Write any pending changes to disk."""
return # Maildir changes are always written immediately. # Maildir changes are always written immediately, so there's nothing
# to do except invalidate our cached toc.
self._last_read = None
def lock(self): def lock(self):
"""Lock the mailbox.""" """Lock the mailbox."""

View File

@ -673,6 +673,9 @@ class TestMaildir(TestMailbox):
self.assertEqual(self._box._lookup(key0), os.path.join('new', key0)) self.assertEqual(self._box._lookup(key0), os.path.join('new', key0))
os.remove(os.path.join(self._path, 'new', key0)) os.remove(os.path.join(self._path, 'new', key0))
self.assertEqual(self._box._toc, {key0: os.path.join('new', key0)}) self.assertEqual(self._box._toc, {key0: os.path.join('new', key0)})
# Be sure that the TOC is read back from disk (see issue #6896
# about bad mtime behaviour on some systems).
self._box.flush()
self.assertRaises(KeyError, lambda: self._box._lookup(key0)) self.assertRaises(KeyError, lambda: self._box._lookup(key0))
self.assertEqual(self._box._toc, {}) self.assertEqual(self._box._toc, {})

View File

@ -123,6 +123,10 @@ C-API
Library Library
------- -------
- Issue #6896: mailbox.Maildir now invalidates its internal cache each time
a modification is done through it. This fixes inconsistencies and test
failures on systems with slightly bogus mtime behaviour.
- Issue #7246 & Issue #7208: getpass now properly flushes input before - Issue #7246 & Issue #7208: getpass now properly flushes input before
reading from stdin so that existing input does not confuse it and reading from stdin so that existing input does not confuse it and
lead to incorrect entry or an IOError. It also properly flushes it lead to incorrect entry or an IOError. It also properly flushes it