IMAP4.__exit__ counterintuitive for with blocks

IMAP4.close closes the selected inbox and commits changes such as deletions. It is not called on IMAP4.__exit__ (only logout is, which doesn't call close in its call stack) however, so: with imaplib.IMAP4_SSL(...) as i: ... would fail to commit those changes. close must be explicitly invoked i.e. with imaplib.IMAP4_SSL(...) as i: ... i.close() This is counterintuitive however, as the with statement is meant to automatically clean up. Another programmer might come along and delete i.close() because it seems unnecessary. Now changes aren't being committed and the programmer doesn't realize it's because of this weird Python idiosyncracy. Python IO such as open commits changes automatically, so I'm not sure why IMAP4 doesn't and only logs out.

But maybe if __exit__ is called with an exception it should roll back. In any case it looks like your proposal could break existing code (e.g. code that uses `with` depending on its current behavior, using some other logic to decide whether to commit or not) and that feels difficult to overcome. Perhaps a new method or flag argument can be added to request that the transactions be automatically committed? On Mon, Oct 30, 2017 at 10:20 AM, Drew <dwarwick96@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

Yeah, a flag for IMAP4 objects sounds like it'd solve backwards-compatibility problems. E.g. imaplib.IMAP4_SSL(..., commit=manual/auto) As for handling errors with automatic commits, we should probably just defer to whatever Python IO does to remain consistent. On Oct 30, 2017, 1:33 PM, at 1:33 PM, Guido van Rossum <guido@python.org> wrote:

On Mon, Oct 30, 2017 at 8:30 PM, Drew <dwarwick96@gmail.com> wrote:
Yeah, at least if it makes sense here too. BTW, it so happens that an old contextlib feature strikes again and allows you to write this in plain English, with punctuation and all: with imaplib.IMAP4_SSL(..) as i, closing(i): ... This one does call .close() regardless of errors, though, and possibly the kind of error may affect whether the commit succeeds or not. Not sure if that matters. -- Koos
-- + Koos Zevenhoven + http://twitter.com/k7hoven +

But maybe if __exit__ is called with an exception it should roll back. In any case it looks like your proposal could break existing code (e.g. code that uses `with` depending on its current behavior, using some other logic to decide whether to commit or not) and that feels difficult to overcome. Perhaps a new method or flag argument can be added to request that the transactions be automatically committed? On Mon, Oct 30, 2017 at 10:20 AM, Drew <dwarwick96@gmail.com> wrote:
-- --Guido van Rossum (python.org/~guido)

Yeah, a flag for IMAP4 objects sounds like it'd solve backwards-compatibility problems. E.g. imaplib.IMAP4_SSL(..., commit=manual/auto) As for handling errors with automatic commits, we should probably just defer to whatever Python IO does to remain consistent. On Oct 30, 2017, 1:33 PM, at 1:33 PM, Guido van Rossum <guido@python.org> wrote:

On Mon, Oct 30, 2017 at 8:30 PM, Drew <dwarwick96@gmail.com> wrote:
Yeah, at least if it makes sense here too. BTW, it so happens that an old contextlib feature strikes again and allows you to write this in plain English, with punctuation and all: with imaplib.IMAP4_SSL(..) as i, closing(i): ... This one does call .close() regardless of errors, though, and possibly the kind of error may affect whether the commit succeeds or not. Not sure if that matters. -- Koos
-- + Koos Zevenhoven + http://twitter.com/k7hoven +
participants (3)
-
Drew
-
Guido van Rossum
-
Koos Zevenhoven