@@ -308,22 +308,28 @@ An :class:`IMAP4` instance has the following methods:
308308 of the IMAP4 QUOTA extension defined in rfc2087.
309309
310310
311- .. method :: IMAP4.idle([ dur] )
311+ .. method :: IMAP4.idle(dur=None )
312312
313313 Return an iterable context manager implementing the ``IDLE `` command
314314 as defined in :rfc: `2177 `.
315315
316- The optional *dur * argument specifies a maximum duration (in seconds) to
317- keep idling. It defaults to ``None ``, meaning no time limit.
318- To avoid inactivity timeouts on servers that impose them, callers are
319- advised to keep this <= 29 minutes. See the note below regarding
316+ The context manager sends the ``IDLE `` command when activated by the
317+ :keyword: `with ` statement, produces IMAP untagged responses via the
318+ :term: `iterator ` protocol, and sends ``DONE `` upon context exit.
319+
320+ The *dur * argument sets a maximum duration (in seconds) to keep idling,
321+ after which iteration will stop. It defaults to ``None ``, meaning no time
322+ limit. Callers wishing to avoid inactivity timeouts on servers that impose
323+ them should keep this <= 29 minutes.
324+ See the :ref: `warning below <windows-pipe-timeout-warning >` if using
320325 :class: `IMAP4_stream ` on Windows.
321326
322- The context manager sends the ``IDLE `` command upon entry, produces
323- responses via iteration, and sends ``DONE `` upon exit.
324- It represents responses as ``(type, datum) `` tuples, rather than the
325- ``(type, [data, ...]) `` tuples returned by other methods, because only
326- one response is represented at a time.
327+ Response tuples produced by the iterator almost exactly match those
328+ returned by other imaplib methods. The difference is that the tuple's
329+ second member is a single response datum, rather than a list of data.
330+ Therefore, in a mailbox where calling ``M.response('EXISTS') `` would
331+ return ``('EXISTS', [b'1']) ``, the idle iterator would produce
332+ ``('EXISTS', b'1') ``.
327333
328334 Example::
329335
@@ -332,22 +338,59 @@ An :class:`IMAP4` instance has the following methods:
332338 typ, datum = response
333339 print(typ, datum)
334340
335- It is also possible to process a burst of responses all at once instead
336- of one at a time. See ` IDLE Context Manager `_ for details.
341+ ('EXISTS', b'1')
342+ ('RECENT', b'1')
337343
338- Responses produced by the iterator will not be returned by
339- :meth: `IMAP4.response `.
344+ Instead of iterating one response at a time, it is also possible to retrieve
345+ the next response along with any immediately available subsequent responses
346+ (e.g. a rapid series of ``EXPUNGE `` events from a bulk delete). This
347+ batch processing aid is provided by the context's ``burst() ``
348+ :term: `generator `:
340349
341- .. note ::
350+ .. method :: idler.burst(interval=0.1)
351+
352+ Yield a burst of responses no more than *interval * seconds apart.
353+
354+ Example::
355+
356+ with M.idle() as idler:
357+
358+ # get the next response and any others following by < 0.1 seconds
359+ batch = list(idler.burst())
360+
361+ print(f'processing {len(batch)} responses...')
362+ print(batch)
363+
364+ processing 3 responses...
365+ [('EXPUNGE', b'2'), ('EXPUNGE', b'1'), ('RECENT', b'0')]
366+
367+ The ``IDLE `` context's maximum duration (the *dur * argument to
368+ :meth: `IMAP4.idle `) is respected when waiting for the first response
369+ in a burst. Therefore, an expired idle context will cause this generator
370+ to return immediately without producing anything. Callers should
371+ consider this if using it in a loop.
372+
373+
374+ .. _windows-pipe-timeout-warning :
375+
376+ .. warning ::
342377
343378 Windows :class: `IMAP4_stream ` connections have no way to accurately
344- respect *dur *, since Windows ``select() `` only works on sockets.
345- However, if the server regularly sends status messages during ``IDLE ``,
346- they will wake our selector and keep iteration from blocking for long.
347- Dovecot's ``imap_idle_notify_interval `` is two minutes by default.
348- Assuming that's typical of IMAP servers, subtracting it from the 29
349- minutes needed to avoid server inactivity timeouts would make 27
350- minutes a sensible value for *dur * in this situation.
379+ respect the *dur * or *interval * arguments, since Windows ``select() ``
380+ only works on sockets.
381+
382+ If the server regularly sends status messages during ``IDLE ``, they will
383+ wake our iterator anyway, allowing *dur * to behave roughly as intended,
384+ although usually late. Dovecot's ``imap_idle_notify_interval `` default
385+ setting does this every 2 minutes. Assuming that's typical of IMAP
386+ servers, subtracting it from the 29 minutes needed to avoid server
387+ inactivity timeouts would make 27 minutes a sensible value for *dur * in
388+ this situation.
389+
390+ There is no such fallback for ``burst() ``, which will yield endless
391+ responses and block indefinitely for each one. It is therefore advised
392+ not to use ``burst() `` with an :class: `IMAP4_stream ` connection on
393+ Windows.
351394
352395
353396.. method :: IMAP4.list([directory[, pattern]])
@@ -655,62 +698,6 @@ The following attributes are defined on instances of :class:`IMAP4`:
655698 .. versionadded :: 3.5
656699
657700
658- .. _idle context manager :
659-
660- IDLE Context Manager
661- --------------------
662-
663- The object returned by :meth: `IMAP4.idle ` implements the context management
664- protocol for the :keyword: `with ` statement, and the :term: `iterator ` protocol
665- for retrieving untagged responses while the context is active.
666- It also has the following method:
667-
668- .. method :: IdleContextManager.burst([interval])
669-
670- Yield a burst of responses no more than *interval * seconds apart.
671-
672- This generator retrieves the next response along with any
673- immediately available subsequent responses (e.g. a rapid series of
674- ``EXPUNGE `` responses after a bulk delete) so they can be efficiently
675- processed as a batch instead of one at a time.
676-
677- The optional *interval * argument specifies a time limit (in seconds)
678- for each response after the first. It defaults to 0.1 seconds.
679- (The ``IDLE `` context's maximum duration is respected when waiting for the
680- first response.)
681-
682- Represents responses as ``(type, datum) `` tuples, just as when
683- iterating directly on the context manager.
684-
685- Example::
686-
687- with M.idle() as idler:
688-
689- # get the next response and any others following by < 0.1 seconds
690- batch = list(idler.burst())
691-
692- print(f'processing {len(batch)} responses...')
693- for typ, datum in batch:
694- print(typ, datum)
695-
696- Produces no responses and returns immediately if the ``IDLE `` context's
697- maximum duration (the *dur * argument to :meth: `IMAP4.idle `) has elapsed.
698- Callers should plan accordingly if using this method in a loop.
699-
700- .. note ::
701-
702- Windows :class: `IMAP4_stream ` connections will ignore the *interval *
703- argument, yielding endless responses and blocking indefinitely for each
704- one, since Windows ``select() `` only works on sockets. It is therefore
705- advised not to use this method with an :class: `IMAP4_stream ` connection
706- on Windows.
707-
708- .. note ::
709-
710- The context manager's type name is not part of its public interface,
711- and is subject to change.
712-
713-
714701.. _imap4-example :
715702
716703IMAP4 Example
0 commit comments