-
-
Notifications
You must be signed in to change notification settings - Fork 32.2k
gh-55454: Add IMAP4 IDLE support to imaplib #122542
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
80 commits
Select commit
Hold shift + click to select a range
572d1e5
gh-55454: Add IMAP4 IDLE support to imaplib
foresto dc71241
gh-55454: Clarify imaplib idle() docs
foresto f41f2bb
docs: words instead of <=
gpshead 8077f2e
docs: improve style in an example
gpshead 24fcdbb
docs: grammatical edit
gpshead 2c76b2f
docs consistency
gpshead 5ef5bb2
comment -> docstring
gpshead 91266e0
docs: refer to imaplib as "this module"
foresto 19c98dc
imaplib: simplify & clarify idle debug message
foresto 882bf2c
imaplib: elaborate in idle context manager comment
foresto f648fec
imaplib: re-raise BaseException instead of bare except
foresto 48f6f76
imaplib: convert private doc string to comment
foresto 013bbf1
docs: correct mistake in imaplib example
foresto acbc4a1
imaplib: simplify example code in doc string
foresto 94c02e8
imaplib: rename _Idler to Idler, update its docs
foresto 0c6c9a4
imaplib: add comment in Idler._pop()
foresto 223c2fa
imaplib: remove unnecessary blank line
foresto e64546c
imaplib: comment on use of unbuffered pipes
foresto f385e44
docs: imaplib: use the reStructuredText :class: role
foresto 3aceaec
Revert "docs: imaplib: use the reStructuredText :class: role"
foresto c8d4d6d
docs: imaplib: use the reST :class: role, escaped
foresto 75fbe8e
Merge branch 'main' into imaplib-idle
gvanrossum c7ed3c5
docs: refer to IMAP4 IDLE instead of just IDLE
foresto b01de95
imaplib: IDLE -> IMAP4 IDLE in exception message
foresto a3f21cd
docs: imaplib idle() phrasing and linking tweaks
foresto 247e6b5
docs: imaplib: avoid linking to an invalid target
foresto 79e3d83
imaplib: update test after recent exception change
foresto 14dfd21
imaplib: rename idle() dur argument to duration
foresto 19253d1
imaplib: bytes.index() -> bytes.find()
foresto b65074e
imaplib: remove no-longer-necessary statement
foresto 5d8a40b
docs: imaplib: concise & valid method links
foresto fc13f75
imaplib: note data types present in IDLE responses
foresto 3221dbc
docs: imaplib: add comma to reST changes header
foresto 564c722
imaplib: sync doc strings with reST docs
foresto c9e8034
docs: imaplib: minor Idler clarifications
foresto 9c4af2c
imaplib: idle: emit (type, [data, ...]) tuples
foresto 59e0c6a
imaplib: while/yield instead of yield from iter()
foresto 2e3e956
imaplib: idle: use deadline idiom when iterating
foresto bdde943
docs: imaplib: state duration/interval arg types
foresto b64c7a5
docs: imaplib: minor rephrasing of a sentence
foresto b73a365
docs: imaplib: reposition a paragraph
foresto ae74499
docs: imaplib: wrap long lines in idle() section
foresto 92d7ce7
docs: imaplib: note: Idler objects require 'with'
foresto 171ebf1
docs: imaplib: say that 29 minutes is 1740 seconds
foresto 5682ef4
docs: imaplib: mark a paragraph as a 'tip'
foresto 656e9f5
docs: imaplib: rephrase reference to MS Windows
foresto 3b70534
imaplib: end doc string titles with a period
foresto 60e2b6f
imaplib: idle: socket timeouts instead of select()
foresto def6ab5
imaplib: Idler: rename private state attributes
foresto 8e0b6b0
imaplib: rephrase a comment in example code
foresto 08a4536
docs: imaplib: idle: use Sphinx code-block:: pycon
foresto c881c8b
docs: whatsnew: imaplib: reformat IMAP4.idle entry
foresto 266a292
imaplib: idle: make doc strings brief
foresto 055a9bd
imaplib: Idler: split assert into two statements
foresto 4d3f020
imaplib: Idler: move assignment out of try: block
foresto 80aaf8d
imaplib: Idler: move __exit__() for readability
foresto 03b5205
imaplib: Idler: move __next__() for readability
foresto 83c8946
imaplib: test: make IdleCmdHandler a global class
foresto be2d2b0
docs: imaplib: idle: collapse double-spaces
foresto de62a3e
imaplib: warn on use of undocumented 'file' attr
foresto 7fc8a24
imaplib: revert import reformatting
foresto 33a1fed
imaplib: restore original exception msg formatting
foresto 40e607a
docs: imaplib: idle: versionadded:: next
foresto 9a07f3b
imaplib: move import statement to where it's used
foresto f47de53
imaplib test: RuntimeWarning on IMAP4.file access
foresto 66d32a0
imaplib: use stacklevel=2 in warnings.warn()
foresto d619580
imaplib test: simplify IMAP4.file warning test
foresto fc8b6f4
imaplib test: pre-idle-continuation response
foresto b767ab6
imaplib test: post-done untagged response
foresto dcd0161
imaplib: downgrade idle-denied exception to error
foresto 53c7a19
imaplib: simplify check for socket object
foresto fcaf355
imaplib: narrow the scope of IDLE socket timeouts
foresto a47bcb4
imaplib: preserve partial reads on exception
foresto 7fc4b78
imaplib: read/readline: save multipart buffer tail
foresto be34141
imaplib: use TimeoutError subclass only if needed
foresto e8a8509
doc: imaplib: elaborate on IDLE response delivery
foresto 8d78010
doc: imaplib: elaborate in note re: IMAP4.response
foresto e8f0532
Merge branch 'main' into imaplib-idle
foresto f650dfa
imaplib: comment on benefit of reading in chunks
foresto 3512858
imaplib: readline(): treat ConnectionError as EOF
foresto File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,6 +10,7 @@ | |
.. changes for IMAP4_SSL by Tino Lange <[email protected]>, March 2002 | ||
.. changes for IMAP4_stream by Piers Lauder <[email protected]>, | ||
November 2002 | ||
.. changes for IMAP4 IDLE by Forest <[email protected]>, August 2024 | ||
|
||
**Source code:** :source:`Lib/imaplib.py` | ||
|
||
|
@@ -187,7 +188,7 @@ However, the *password* argument to the ``LOGIN`` command is always quoted. If | |
you want to avoid having an argument string quoted (eg: the *flags* argument to | ||
``STORE``) then enclose the string in parentheses (eg: ``r'(\Deleted)'``). | ||
|
||
Each command returns a tuple: ``(type, [data, ...])`` where *type* is usually | ||
Most commands return a tuple: ``(type, [data, ...])`` where *type* is usually | ||
``'OK'`` or ``'NO'``, and *data* is either the text from the command response, | ||
or mandated results from the command. Each *data* is either a ``bytes``, or a | ||
tuple. If a tuple, then the first part is the header of the response, and the | ||
|
@@ -307,6 +308,93 @@ An :class:`IMAP4` instance has the following methods: | |
of the IMAP4 QUOTA extension defined in rfc2087. | ||
|
||
|
||
.. method:: IMAP4.idle(duration=None) | ||
|
||
Return an :class:`!Idler`: an iterable context manager implementing the | ||
IMAP4 ``IDLE`` command as defined in :rfc:`2177`. | ||
|
||
The returned object sends the ``IDLE`` command when activated by the | ||
:keyword:`with` statement, produces IMAP untagged responses via the | ||
foresto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
:term:`iterator` protocol, and sends ``DONE`` upon context exit. | ||
foresto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
All untagged responses that arrive after sending the ``IDLE`` command | ||
(including any that arrive before the server acknowledges the command) will | ||
be available via iteration. Any leftover responses (those not iterated in | ||
the :keyword:`with` context) can be retrieved in the usual way after | ||
``IDLE`` ends, using :meth:`IMAP4.response`. | ||
|
||
Responses are represented as ``(type, [data, ...])`` tuples, as described | ||
foresto marked this conversation as resolved.
Show resolved
Hide resolved
|
||
in :ref:`IMAP4 Objects <imap4-objects>`. | ||
|
||
The *duration* argument sets a maximum duration (in seconds) to keep idling, | ||
after which any ongoing iteration will stop. It can be an :class:`int` or | ||
:class:`float`, or ``None`` for no time limit. | ||
Callers wishing to avoid inactivity timeouts on servers that impose them | ||
should keep this at most 29 minutes (1740 seconds). | ||
Requires a socket connection; *duration* must be ``None`` on | ||
:class:`IMAP4_stream` connections. | ||
|
||
.. code-block:: pycon | ||
|
||
>>> with M.idle(duration=29 * 60) as idler: | ||
... for typ, data in idler: | ||
... print(typ, data) | ||
... | ||
EXISTS [b'1'] | ||
RECENT [b'1'] | ||
|
||
|
||
.. method:: Idler.burst(interval=0.1) | ||
|
||
Yield a burst of responses no more than *interval* seconds apart | ||
(expressed as an :class:`int` or :class:`float`). | ||
|
||
This :term:`generator` is an alternative to iterating one response at a | ||
time, intended to aid in efficient batch processing. It retrieves the | ||
next response along with any immediately available subsequent responses. | ||
(For example, a rapid series of ``EXPUNGE`` responses after a bulk | ||
delete.) | ||
|
||
Requires a socket connection; does not work on :class:`IMAP4_stream` | ||
connections. | ||
|
||
.. code-block:: pycon | ||
|
||
>>> with M.idle() as idler: | ||
... # get a response and any others following by < 0.1 seconds | ||
... batch = list(idler.burst()) | ||
... print(f'processing {len(batch)} responses...') | ||
... print(batch) | ||
... | ||
processing 3 responses... | ||
[('EXPUNGE', [b'2']), ('EXPUNGE', [b'1']), ('RECENT', [b'0'])] | ||
|
||
.. tip:: | ||
|
||
The ``IDLE`` context's maximum duration, as passed to | ||
:meth:`IMAP4.idle`, is respected when waiting for the first response | ||
in a burst. Therefore, an expired :class:`!Idler` will cause this | ||
generator to return immediately without producing anything. Callers | ||
should consider this if using it in a loop. | ||
|
||
|
||
.. note:: | ||
|
||
The iterator returned by :meth:`IMAP4.idle` is usable only within a | ||
:keyword:`with` statement. Before or after that context, unsolicited | ||
responses are collected internally whenever a command finishes, and can | ||
be retrieved with :meth:`IMAP4.response`. | ||
|
||
.. note:: | ||
|
||
The :class:`!Idler` class name and structure are internal interfaces, | ||
subject to change. Calling code can rely on its context management, | ||
iteration, and public method to remain stable, but should not subclass, | ||
instantiate, compare, or otherwise directly reference the class. | ||
|
||
.. versionadded:: next | ||
|
||
|
||
.. method:: IMAP4.list([directory[, pattern]]) | ||
|
||
List mailbox names in *directory* matching *pattern*. *directory* defaults to | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.